다른 문자열의 하위 문자열이 아닌 문자열 검색 및 바꾸기

다른 문자열의 하위 문자열이 아닌 문자열 검색 및 바꾸기

다음과 같은 대체 목록이 있습니다.

search_and -> replace
big_boy -> bb
little_boy -> lb
good_dog -> gd
...

위의 내용을 바꿔야 하지만 동시에 다음과 같이 긴 문자열을 일치시키는 것을 피해야 합니다.

big_boys
good_little_boy

나는 이것을 시도했습니다 :

sed -i -r "s/$(\W){search}(\W)/$\1{replacement}\2/g"

그러나 다음과 같이 문자열(이 경우 "good_dog")이 줄 끝에 나타나면 위 방법이 작동하지 않습니다.

Mary had a 'little_boy', good_little_boy, $big_boy, big_boys and good_dog

Mary had a 'lb', good_little_boy, $bb, big_boys and good_dog

문자열이 줄의 시작 부분에도 나타날 때 위의 내용이 작동할지 의심됩니다. 찾아 교체할 수 있는 좋은 방법이 있나요?

답변1

GNU sed를 사용하는 경우(과도한 노출은 -i사용 중임을 나타냄)"단어 경계" 이스케이프\b:

sed -i "s/\b$SEARCH\b/$REPLACE/g"

\b단어 경계의 정확한 일치: 한쪽의 문자는 "단어" 문자이지만 다른 쪽의 문자는 그렇지 않습니다. 너비가 0인 일치이므로 sum \1값을 보존하기 위해 하위 그룹 캡처를 사용할 필요가 없습니다 \2. \B정반대인 또 다른 것이 있습니다 .


GNU sed를 사용하지 않는 경우 캡처 하위 모드에서 줄의 시작과 끝을 번갈아 사용할 수 있습니다 (\W|^). 이는 단어가 아닌 문자 또는 줄의 시작과 일치하고, (\W|$)단어가 아닌 문자 또는 줄의 끝과 일치합니다. 이 경우에도 \1and를 그대로 사용합니다. 어쨌든, \2GNU가 아닌 일부 제품은 적어도 확장 모드에서 sed이를 지원하므로 어쨌든 시도해 볼 가치가 있습니다.\b

답변2

이식성을 높이고 싶다면 다음을 사용할 수 \<있습니다 \>.

sed -i "s/\<$SEARCH\>/$REPLACE/g" file

\<\>gsed, ssed, sed15, sed16, sedmod에서 작동합니다 .

\b그리고 \Bgsed에서만 작동합니다.

에서는 Mac OSX다음 구문을 사용해야 합니다.

sed -i '' -e "/[[:<:]]$SEARCH[[:>:]]/$REPLACE/g" file

답변3

\b모든 플랫폼을 지원하는 Perl을 사용할 수도 있습니다 . 교체 목록이 표시된 형식(구분됨 ->)이라고 가정하면 다음을 수행할 수 있습니다.

perl -F"->" -ane 'chomp;$rep{$F[0]}=${$F[1]}; 
                  END{open(A,"file"); 
                    while(<A>){
                        s/\b$_\b/$rep{$_}/g for keys(%rep); 
                        print
                    }
                  }' replacements

설명하다

  • Perl이 awk처럼 동작하도록 만들어 -a필드를 배열, 첫 번째 필드, 두 번째 필드 @F등 으로 자동 분할합니다. awk와 마찬가지로 입력 필드 구분자를 설정합니다. 이는 "입력 파일을 한 줄씩 읽고 주어진 스크립트를 각 줄에 적용한다"는 의미입니다.$F[0]$F[1]-F-F-n-e

  • chomp\n: 줄 끝에서 개행 문자( )를 제거합니다.

  • $rep{$F[0]}=${$F[1]};%rep: 교체할 패턴(첫 번째 필드 $F[0])이 키이고 교체( $F[1])가 값이 되도록 해시를 채웁니다 . *: END{}입력 파일()을 읽은 후 실행됩니다.replacements
  • open(A,"file")file: 파일 핸들을 사용하여 읽기 위해 파일을 엽니다 A.
  • while (<A>): 파일을 한 줄씩 읽습니다.
  • s/// for keys(%rep): 이것은 해시의 모든 키를 반복하여 %rep각 키를 특수 변수로 저장합니다 $_. s///대체 연산자이며 설명된 것과 동일한 대체를 수행합니다 .마이클의 대답.

파일을 읽고 sed다른 답변에 표시된 내용을 사용할 수도 있습니다.

$ sed 's/->/\t/' replacements | 
    while IFS=$'\t' read from to; do sed -i "s/\b$from\b/$to/g" file; done

관련 정보