이 예를 보았습니다.
hello=ho02123ware38384you443d34o3434ingtod38384day
echo ${hello//[0-9]/}
다음 구문을 따릅니다. ${variable//pattern/replacement}
불행히도 pattern
필드는 전체 정규식 구문을 지원하지 않는 것 같습니다 ( 예를 들어 .
또는을 사용하는 경우 \s
리터럴 문자와 일치하려고 시도합니다).
전체 정규식 구문을 사용하여 문자열을 검색 / 바꾸려면 어떻게해야합니까?
답변
sed 사용 :
MYVAR=ho02123ware38384you443d34o3434ingtod38384day
echo "$MYVAR" | sed -e 's/[a-zA-Z]/X/g' -e 's/[0-9]/N/g'
# prints XXNNNNNXXXXNNNNNXXXNNNXNNXNNNNXXXXXXNNNNNXXX
후속 작업 -e
은 순서대로 처리됩니다. 또한 g
표현식 의 플래그는 입력의 모든 항목과 일치합니다.
이 방법을 사용하여 좋아하는 도구를 선택할 수도 있습니다 (예 : perl, awk).
echo "$MYVAR" | perl -pe 's/[a-zA-Z]/X/g and s/[0-9]/N/g'
이렇게하면 더 창의적인 일치를 수행 할 수 있습니다 … 예를 들어 위의 캡처에서 첫 번째 표현식에 일치하는 항목이 없으면 숫자 대체가 사용되지 않습니다 (지연 and
평가 로 인해 ). 그리고 물론, 당신은 당신의 입찰을 위해 Perl의 완전한 언어 지원을 가지고 있습니다.
답변
이것은 실제로 순수한 bash에서 수행 할 수 있습니다.
hello=ho02123ware38384you443d34o3434ingtod38384day
re='(.*)[0-9]+(.*)'
while [[ $hello =~ $re ]]; do
hello=${BASH_REMATCH[1]}${BASH_REMATCH[2]}
done
echo "$hello"
… 수율 …
howareyoudoingtodday
답변
이 예제는 sed를 사용할 필요없이 bash에서도 작동합니다.
#!/bin/bash
MYVAR=ho02123ware38384you443d34o3434ingtod38384day
MYVAR=${MYVAR//[a-zA-Z]/X}
echo ${MYVAR//[0-9]/N}
문자 클래스 대괄호 표현식을 사용할 수도 있습니다.
#!/bin/bash
MYVAR=ho02123ware38384you443d34o3434ingtod38384day
MYVAR=${MYVAR//[[:alpha:]]/X}
echo ${MYVAR//[[:digit:]]/N}
산출
XXNNNNNXXXXNNNNNXXXNNNXNNXNNNNXXXXXXNNNNNXXX
그러나 @Lanaru가 알고 싶었던 것은 내가 질문을 올바르게 이해했다면 “전체”또는 PCRE 확장이 왜 필요한지입니다. \s\S\w\W\d\D
등이 php ruby python 등에서 지원 작동하지 않는 . 이러한 확장은 Perl 호환 정규식 (PCRE)에서 가져온 것입니다. 다른 형태의 쉘 기반 정규식과 호환되지 않을 수 있습니다.
작동하지 않습니다.
#!/bin/bash
hello=ho02123ware38384you443d34o3434ingtod38384day
echo ${hello//\d/}
#!/bin/bash
hello=ho02123ware38384you443d34o3434ingtod38384day
echo $hello | sed 's/\d//g'
모든 리터럴 “d”문자가 제거 된 출력
ho02123ware38384you44334o3434ingto38384ay
하지만 다음은 예상대로 작동합니다.
#!/bin/bash
hello=ho02123ware38384you443d34o3434ingtod38384day
echo $hello | perl -pe 's/\d//g'
산출
howareyoudoingtodday
좀 더 명확 해지기를 바라지 만 아직 혼란스럽지 않다면 REG_ENHANCED 플래그가 활성화 된 Mac OS X에서이 작업을 시도해보십시오.
#!/bin/bash
MYVAR=ho02123ware38384you443d34o3434ingtod38384day;
echo $MYVAR | grep -o -E '\d'
대부분의 * nix 버전에서는 다음 출력 만 표시됩니다.
d
d
d
nJoy!
답변
반복적 인 호출을하고 성능에 관심이있는 경우이 테스트는 BASH 메서드가 sed 및 다른 외부 프로세스보다 15 배 더 빠르다는 것을 보여줍니다.
hello=123456789X123456789X123456789X123456789X123456789X123456789X123456789X123456789X123456789X123456789X123456789X
P1=$(date +%s)
for i in {1..10000}
do
echo $hello | sed s/X//g > /dev/null
done
P2=$(date +%s)
echo $[$P2-$P1]
for i in {1..10000}
do
echo ${hello//X/} > /dev/null
done
P3=$(date +%s)
echo $[$P3-$P2]
답변
[[:digit:]]
패턴으로 사용 (이중 대괄호 참고) :
$ hello=ho02123ware38384you443d34o3434ingtod38384day
$ echo ${hello//[[:digit:]]/}
howareyoudoingtodday
답변을 요약하고 싶었습니다 (특히 @ nickl-의 https://stackoverflow.com/a/22261334/2916086 ).
답변
나는 이것이 고대의 스레드라는 것을 알고 있지만, 그것은 Google에서 처음으로 히트 한 것이었고 resub
, 여러 $ 1, $ 2 등에 대한 지원을 추가 하는 다음 을 함께 공유하고 싶었습니다 .
#!/usr/bin/env bash
############################################
### resub - regex substitution in bash ###
############################################
resub() {
local match="$1" subst="$2" tmp
if [[ -z $match ]]; then
echo "Usage: echo \"some text\" | resub '(.*) (.*)' '\$2 me \${1}time'" >&2
return 1
fi
### First, convert "$1" to "$BASH_REMATCH[1]" and 'single-quote' for later eval-ing...
### Utility function to 'single-quote' a list of strings
squot() { local a=(); for i in "$@"; do a+=( $(echo \'${i//\'/\'\"\'\"\'}\' )); done; echo "${a[@]}"; }
tmp=""
while [[ $subst =~ (.*)\${([0-9]+)}(.*) ]] || [[ $subst =~ (.*)\$([0-9]+)(.*) ]]; do
tmp="\${BASH_REMATCH[${BASH_REMATCH[2]}]}$(squot "${BASH_REMATCH[3]}")${tmp}"
subst="${BASH_REMATCH[1]}"
done
subst="$(squot "${subst}")${tmp}"
### Now start (globally) substituting
tmp=""
while read line; do
counter=0
while [[ $line =~ $match(.*) ]]; do
eval tmp='"${tmp}${line%${BASH_REMATCH[0]}}"'"${subst}"
line="${BASH_REMATCH[$(( ${#BASH_REMATCH[@]} - 1 ))]}"
done
echo "${tmp}${line}"
done
}
resub "$@"
##################
### EXAMPLES ###
##################
### % echo "The quick brown fox jumps quickly over the lazy dog" | resub quick slow
### The slow brown fox jumps slowly over the lazy dog
### % echo "The quick brown fox jumps quickly over the lazy dog" | resub 'quick ([^ ]+) fox' 'slow $1 sheep'
### The slow brown sheep jumps quickly over the lazy dog
### % animal="sheep"
### % echo "The quick brown fox 'jumps' quickly over the \"lazy\" \$dog" | resub 'quick ([^ ]+) fox' "\"\$low\" \${1} '$animal'"
### The "$low" brown 'sheep' 'jumps' quickly over the "lazy" $dog
### % echo "one two three four five" | resub "one ([^ ]+) three ([^ ]+) five" 'one $2 three $1 five'
### one four three two five
### % echo "one two one four five" | resub "one ([^ ]+) " 'XXX $1 '
### XXX two XXX four five
### % echo "one two three four five one six three seven eight" | resub "one ([^ ]+) three ([^ ]+) " 'XXX $1 YYY $2 '
### XXX two YYY four five XXX six YYY seven eight
@Charles Duffy 에게 H / T 다시 :(.*)$match(.*)