여러 줄 문자열을 수동 이스케이프 없이 여러 줄 문자열로 교체

여러 줄 문자열을 수동 이스케이프 없이 여러 줄 문자열로 교체

텍스트 파일이 있고 에 포함된 (여러 줄) 문자열을 에 포함된 다른 문자열로 바꾸고 싶다고 가정해 보겠습니다 text.txt. 어떻게 해야 합니까? (저는 정규식을 사용하고 싶지 않습니다. 실제로는 에 포함된 문자열을 에 포함된 텍스트로 바꾸고 싶습니다.before.txtafter.txtbefore.txtafter.txttext.txt

다음에서 제안된 방법을 사용하고 싶습니다. https://unix.stackexchange.com/a/26289/288916

나는 시도했다:

perl -i -p0e 's/`cat before.txt`/`cat after.txt`/se' text.txt

그러나 내가 완전히 바보가 아니고 사소한 일을 망치지 않는 한, cat이 있는 파일에서 찾을 문자열을 로드하도록 이것을 확장할 수는 없습니다.

아마도 탈출에 문제가 있는 것 같습니다. 파일에는 before.txt다음과 같은 항목이 포함되어 있습니다 /[]".


@ilkkachu에게 감사드립니다. 다음을 시도했습니다.

perl -i -0 -pe '$b = `cat before.txt`; $a = `cat after.txt`; s/\Q$b\E/$a/s\' text.txt

, 하지만 여전히 작동하지 않습니다. 이전의 문자열이 문자열을 교체할 전체 줄과 정확히 일치하는지 확인하여 한 인스턴스에서 작동하도록 만들었습니다. 하지만 줄 시작 부분에 없는 문자열을 바꾸는 것처럼 작동하지 않습니다. 예: text.txt파일에 다음이 포함되어 있습니다:

Here is 
some text.

before.txt포함하다:text

after.txt포함하다:whatever

기회 없음.

답변1

perl -i -p0e 's/`cat before.txt`/`cat after.txt`/se' text.txt

여기에서는 작은따옴표 안에 백틱이 있으므로 쉘은 이를 처리하지 않지만 Perl은 이를 있는 그대로 봅니다. 또, 펄반품백틱은 인용 형식으로 지원되지만 에서는 사용됩니다 s///.

Perl 명령줄에서 또는 를 사용하는 한 -0여러 줄 모드를 사용하는 것은 문제가 되지 않습니다 . -0777( -0텍스트 파일에는 없는 NUL 문자로 줄을 구분하여 -0777전체 파일을 한 번에 읽습니다.)

큰따옴표를 사용하여 이를 수행할 수 있지만 이렇게 하면 Perl 스크립트에서 파일 내용이 직접 확장되며 모든 특수 문자는 스크립트의 일부로 간주됩니다. 단일 슬래시로 인해 s///연산자가 종료되고 문제가 발생합니다.

대신 Perl이 파일을 읽도록 하십시오:

perl -i -0 -pe '$b = `cat before.txt`; $a = `cat after.txt`; s/$b/$a/s' text.txt

여기서의 내용은 before.txt여전히 ​​정규식으로 처리됩니다. 중지하려면 s/\Q$b\E/$a/s대신 사용하세요.

나는 당신이 e그 플래그를 사용하고 싶지 않을 것이라고 생각합니다 s///. 이는 대체가 Perl 표현식으로 처리되도록 합니다(이것은 쉘이 파일 내용을 Perl 명령줄로 확장하도록 허용하는 경우에만 실제로 중요합니다).


후자의 예에는 평소와 같이 개행 문자를 나타내는 some text.\nin text.txttext\nin 이 있습니다 . 파일이 Perl에 로드되면 있는 그대로 가져오므로 마지막 개행 문자 도 중요합니다. 다른 파일에는 개행 앞에 점이 있고 다른 파일에는 점이 없으므로 일치하지 않습니다.before.txt\nbefore.txt

chomp $b;파일을 로드한 후 가능한 후행 줄 바꿈을 제거할 수 있습니다 . 다음을 사용하여 가능한 후행 개행 문자를 제거할 수 있습니다 $b =~ s/\n$//;.

$ perl -0 -pe '$b = `cat before.txt`; $a = `cat after.txt`; $b =~ s/\n$//; $a =~ s/\n$//; s/$b/$a/s' text.txt
Here is 
some whatever.

답변2

작은따옴표 안의 역따옴표는 문자 그대로 처리됩니다. 제공한 예제에서는 이를 큰따옴표로 바꿀 수 있어야 합니다.

백틱도 어떤 이유로 바람직하지 않으므로 여기서는 다음과 같이 변경했습니다.$( )

perl -i -p0e "s/$(cat before.txt)/$(cat after.txt)/se" text.txt

참고: 저는 단지 귀하의 인용 문제를 해결하는 중일 뿐 귀하의 명령이 귀하의 의도를 달성할 것이라는 보장은 없습니다.

관련 정보