특정 단어가 앞에 나오지 않는 모든 단어를 사용 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 Smith
and 를 다룰 필요가 없습니다 Frank Smith
. Smith
이전에 존재하지 않았던 매칭 방법이 필요합니다 .John
답변1
이는 정규식이 거꾸로 보일 수 있는 모든 언어에서 쉽습니다. 물론 Perl이 목록의 첫 번째입니다.
perl -pe 's/(?<!John\W)Smith/John/g' <<< "John Smith and Jane Johnson talk about Smith's car."
약점은 "John"과 "Smith" 사이에 단어가 아닌 문자가 여러 개 있다는 것입니다. 불행하게도 +
for와 같은 수량자는 \W
"가변 길이 역방향 조회가 구현되지 않음" 오류를 발생시킬 수 있습니다.
답변2
편집하다.. 귀하의 의견과 관련하여 .. 이것은 새로운 스크립트이며 (예를 들어) William 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'
당신은 만족할 수 있습니다윌리엄그의 이름을 다음에 추가하세요또는예를 들어 목록을 작성하십시오.
sed -r 's/\<(William|John|...
원본 스크립트입니다
sed -r 's/(^|[[:punct:]] |\<[a-z]+ )(Smith\>)/\1John/'
답변3
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'
이것이 트릭을 수행하는 것 같습니다.