정규식 및 Sed / Perl : 다른 단어 앞에 ISN이없는 단어 일치


11

특정 단어가 앞에 있지 않은 단어를 모두 사용 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합니다.


어떤 sed에 대해 이야기하고 있습니까?
Ignacio Vazquez-Abrams

리눅스에서 GNU sed 4.2.1
jonescb

답변:


8

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

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

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


6

편집 .. 귀하의 의견은 .. 여기 (예.) 윌리엄 스미스에 대한 우려 자체를하지 않는 새로운 스크립트입니다 다시. 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/'

이것은 효과가 있지만 내가 찾은 한 가지 문제는 Smith 앞의 단어가 대문자 인 경우 (예 : 문장의 첫 단어 뒤에 오는 경우) 일치하지 않는다는 것입니다. manatwork의 perl 솔루션은 다른 상황에서 실패하더라도 그 문제가 없습니다. 다행히도 내 텍스트 파일에는 Mr.와 같은 제목이나 성을 가진 사람들이 없습니다.
jonescb

네 감사합니다 ... 수정 된 스크립트를 게시했습니다 ...
Peter.O

1
 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'

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


예를 들어“Smith와 Jane Johnson이 Smith의 차에 대해 이야기합니다.”와 같이 이름 앞에 다른 단어가 없으면 실패합니다.
manatwork

2
[^John]중 하나 여야합니다 하나 개의 문자와 일치 J, o, h또는 n. 나는 이것이 당신이 의도 한 것 의심합니다. 정규 표현식에는 부정 구조가 없습니다 (Perl에는 (?!…)and (?<!…)가 있지만 부정으로 생각하면 예상대로 작동하지 않을 것입니다).
Gilles 'SO- 악한 중지

@Juaco : 테이크 -2는 작동하지만 예상치 못한 데이터에 취약합니다. 비슷한 방법을 사용했습니다 (약간 마지 못해도). sed부풀린 sed 논리를 사용 하지 않고 사용 temp1하면 거의 항상 괜찮을 것입니다! 그 버스를 조심하십시오. 이 가능성을 완화하기 위해 라틴 스크립트 텍스트 파일에서 거의 발생하지 않는 문자 (예 : 16 진수 값 \ x01 \ x02) 또는 이들의 조합 또는 \ xe188b4 UTF-8 로케일을 사용하는 것이 좋습니다 (ሴ- ETHIOPIC SYLLABLE SEE). 예 : echo -e 'Z' |sed 's/./\xe1\x88\xb4/'=> 로케일이 UTF-8 인 경우.
Peter.O
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.