정규식 및 Sed / Perl : 다른 단어 앞에 ISN이없는 단어 일치 car. 나는 다음과 같이

특정 단어가 앞에 있지 않은 단어를 모두 사용 sed하거나 perl바꾸고 싶습니다 .

예를 들어, 영화 줄거리를 포함하는 텍스트 파일이 있는데, 캐릭터의 성을 모두 이름으로 바꾸고 싶지만 이름이 성을 바로 앞에 올 수없는 경우에만 해당합니다.

샘플 텍스트는 다음과 같습니다.

John Smith and Jane Johnson talk about Smith's car.

나는 다음과 같이 보이기를 원한다.

John Smith and Jane Johnson talk about John's car.

방금 수행 sed 's/Smith/John/' file하면 다음과 같이됩니다.

John John and Jane Johnson talk about John's car.

성 앞에 오는 이름은 항상 동일합니다. 내가 처리하지 않습니다 John SmithFrank Smith. 나는 그것을 선행 Smith하지 않는 일치하는 방법이 필요 John합니다.



답변

정규 표현식이 뒤쳐 질 수있는 모든 언어로 쉽게 사용할 수 있습니다. 물론 Perl은 목록에서 첫 번째입니다.

perl -pe 's/(?<!John\W)Smith/John/g' <<< "John Smith and Jane Johnson talk about Smith's car."

약점은 “John”과 “Smith”사이에 단어가 아닌 문자가 두 개 이상있는 것입니다. 불행하게도 같은 정량 +에 대한 \W올릴 것이다 오류 “변수 길이는 구현되지 lookbehind”.


답변

편집 .. 귀하의 의견은 .. 여기 (예.) 윌리엄 스미스에 대한 우려 자체를하지 않는 새로운 스크립트입니다 다시. Smith (변경되지 않은) 로 유지하는 패턴을 일시적으로 난독 화합니다 .

sed -r 's/\<(John) (Smith)\>/\1\x01x\2/g; 
        s/\<Smith\>/John/g;  s/\x01x/ /g'

당신이 염려되는 경우 씨 씨 부인 … 다음이 작동합니다.

sed -r 's/\<(John|((M(r|rs|s))\.?)) (Smith)\>/\1\x01x\5/g
        s/\<Smith\>/John/g; s/\x01x/ /g'

예를 들어 William 을 이름 이나 목록 에 추가하여 William 을 수용 할 수 있습니다 .
sed -r 's/\<(William|John|...


이것은 원래 스크립트입니다

sed -r 's/(^|[[:punct:]] |\<[a-z]+ )(Smith\>)/\1John/'

답변

 sed -r 's/([^John] )Smith/\1John/g;s/([^Jane] )Johnson/\1Jane/g'

()은 성 앞에 이름이 아닌 이름을 캡처하므로 대체시 역 참조됩니다.

편집하다

@manatwork, 길

네가 옳아. 어때요?

sed -r 's/(John Smith)/temp1/g;s/Smith/John/g;s/temp1/John Smith/g'

이것은 트릭을 수행하는 것 같습니다.