2012-07-19 2 views
1

bash를 사용하여 regex에 대한 고급 정규식 정보를 찾고 있었지만 많은 정보를 찾지 못했습니다.bash에서 regex를 사용하는 문자열에서 여러 일치가 발생했습니다

여기에 개념은 단순한 문자열로,이다 :

myString="DO-BATCH BATCH-DO" 

if [[ $myString =~ ([[:alpha:]]*)-([[:alpha:]]*) ]]; then 
echo ${BASH_REMATCH[1]} #first perens 
echo ${BASH_REMATCH[2]} #second perens 
echo ${BASH_REMATCH[0]} #full match 
fi 

outputs: 
BATCH 
DO 
DO-BATCH 

그래서 그것을 잘 수행하는 첫 경기 (BATCH-DO)하지만 두 번째 경기를 당겨 어떻게 (DO-BATCH)? 난 그냥 빈 여기 그리기 및 bash 정규식에 대한 많은 정보를 찾을 수 없습니다.

+1

"DO-BATCH"가 문자열에 나타나지 않으므로 묻는 것이 명확하지 않습니다. 그러나'$ {BASH_REMATCH [3]} '을 "BATCH"등과 같게하고 싶습니까? – chepner

+0

올바른 결과 ... 죄송합니다. $ {BASH_REMATCH [3]} == "BATCH"와 $ {BASH_REMATCH [4]} == "DO" –

답변

2

OK 그래서 나는 이런 짓을 한 가지 방법은 for 루프에 넣어하는 것입니다

myString="DO-BATCH BATCH-DO" 
for aString in ${myString[@]}; do 
    if [[ ${aString} =~ ([[:alpha:]]*)-([[:alpha:]]*) ]]; then 
    echo ${BASH_REMATCH[1]} #first perens 
    echo ${BASH_REMATCH[2]} #second perens 
    echo ${BASH_REMATCH[0]} #full match 
    fi 
done 

which outputs: 
DO 
BATCH 
DO-BATCH 
BATCH 
DO 
BATCH-DO 

내가 가지 가능한 한 정규 표현식에서 모든 당겨 기대했지만 작동한다.

+0

'perl'은 그것의'g' 플래그를 통해 반복 매칭이라는 개념을 지원합니다. 매칭 연산자'm //'를 사용하지만, 가장 잘 알고있는'bash'는 이에 해당하지 않습니다. – chepner

1

대답에서 myString은 배열이 아니지만 배열 참조를 사용하여 액세스합니다. 배열의 0 번째 요소는 변수 이름 만 참조 할 수 있고 그 반대도 가능하기 때문에 Bash에서 작동합니다. 그 의미는 다음과 같이 사용할 수 있다는 뜻입니다.

for aString in $myString; do 

이 경우에도 같은 결과가 나타납니다.

질문에 출력에 "BATCH-DO"가 포함되어 있다고 가정 해보십시오. 나는 "DO-BATCH"를 얻습니다. 그래서 이것은 오타라고 추측합니다.

for 루프를 사용하지 않고 추가 문자열을 얻는 유일한 방법은 긴 정규 표현식을 사용하는 것입니다. 그건 그렇고, Bash 정규 표현식을 변수에 넣는 것이 좋습니다. 그것은 특정 유형 훨씬 쉽게 그 (가) 예를 들어, 공백 또는 특수 문자가 포함 된 (사용할 수있게

pattern='(([[:alpha:]]*)-([[:alpha:]]*)) +(([[:alpha:]]*)-([[:alpha:]]*))' 
[[ $myString =~ $pattern ]] 
declare -p BASH_REMATCH #dump the array 

출력을 :.

당신이 개인을 캡처 할 경우 괄호의 추가 설정이 필요
declare -ar BASH_REMATCH='([0]="DO-BATCH BATCH-DO" [1]="DO-BATCH" [2]="DO" [3]="BATCH" [4]="BATCH-DO" [5]="BATCH" [6]="DO")' 

부분 문자열을 추출해야 할 경우 if을 사용할 필요가 없으므로 각 단어가 필요없는 경우 괄호 안의 집합을 제거 할 수 있습니다.

하위 문자열 만 추출하면됩니다. 오직만 필요하다.은 일치를 기반으로 조건부 조치를 취합니다.

또한 전체 일치가 포함되어 있기 때문에 ${BASH_REMATCH[0]}은 정규 표현식과 상당히 다를 수 있습니다. 나는 주위를 엉망 다음과 같이 결국

+0

예 오타를 편집하여 출력하는 것을 잊었습니다. 감사. 예 myString은 배열이 아닙니다. 나는 처음에 그것을 만들었지 만, for 루프를 위해 그것을 필요로하지 않는다는 것을 발견했다. 나는 조금 뒤죽박죽을 읽었고 배열을 변수로 설정하기 위해 read -a를 사용했다. 나는 무엇을 선언하는지 잘 모르겠다. -p BASH_REMATCH는 배열의 whats리스트를 제외하고 나에게 줄 것이다. –

+0

@ pn1dude : 예,'declare -p BASH_REMATCH'는 테스트하는 동안 배열의 내용을 덤프하는 편리한 방법입니다. –

0

당 @Dennis 윌리엄슨의 포스트 :

myString="DO-BATCH BATCH-DO" 
pattern='(([[:alpha:]]*)-([[:alpha:]]*)) +(([[:alpha:]]*)-([[:alpha:]]*))' 

[[ $myString =~ $pattern ]] && { read -a myREMatch <<< ${BASH_REMATCH[@]}; } 

echo "\${myString} -> ${myString}" 
echo "\${#myREMatch[@]} -> ${#myREMatch[@]}" 

for ((i = 0; i < ${#myREMatch[@]}; i++)); do 
    echo "\${myREMatch[$i]} -> ${myREMatch[$i]}" 
done 

이 거기에있을 2 개 값이 있어야합니다 mystring에를 제외하고 잘 작동합니다. 그래서 나는 그것이 재미 있기 때문에 이것을 게시하고 재미있게 놀고있었습니다. 그러나이보다 일반적인 얻을 페어링 된 그룹의 양을 해결하기 위해 (즉, DO-BATCH)를 내 원래의 대답의 수정 된 버전으로 갈거야 : 나는 여러 경기 같은 perlre를 좋아했을

myString="DO-BATCH BATCH-DO" 
myRE="([[:alpha:]]*)-([[:alpha:]]*)" 

read -a myString <<< $myString 

for aString in ${myString[@]}; do 
    echo "\${aString} -> ${aString}" 
    if [[ ${aString} =~ ${myRE} ]]; then 
    echo "\${BASH_REMATCH[@]} -> ${BASH_REMATCH[@]}" 
    echo "\${#BASH_REMATCH[@]} -> ${#BASH_REMATCH[@]}" 
    for ((i = 0; i < ${#BASH_REMATCH[@]}; i++)); do 
     echo "\${BASH_REMATCH[$i]} -> ${BASH_REMATCH[$i]}" 
    done 
    fi 
done 

하지만이 잘 작동합니다.단어 DO-BATCH의 작은 (더 간결) 세트를 찾기 위해 내부 괄호를 제거하여

myRE="([[:alpha:]]*-[[:alpha:]]*)" 

:

0

이 (허용 대답 없음) 년 오래된 질문이지만은 정규식 패턴이 단순화 될 수있다 및 BATCH-DO?

18:10 시간 답변에 나를 위해 작동합니다. $ {BASH_REMATCH [0]}와 $ {BASH_REMATCH [1]}은 2 개의 단어를 찾았습니다.

관련 문제