将多行字符串替换为多行字符串,无需手动转义

将多行字符串替换为多行字符串,无需手动转义

假设我有一个文本文件,我想用 中包含的另一个字符串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

,但它仍然无法正常工作。我通过确保 before 中的字符串与要替换字符串的整行完全匹配来使其在一个实例中工作。但它不起作用,例如替换在行开头找不到的字符串。示例: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

在这里,单引号内有反引号,因此 shell 不会处理它们,但 Perl 按原样查看它们。再说一遍,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 表达式(只有当您让 shell 将文件内容扩展到 Perl 命令行时,这才真正重要)。


在后面的示例中,您有some text.\nintext.txttext\nin before.txt,其中\n照常代表换行符。当文件加载到 Perl 中时,它们会按原样获取,因此最后的换行符也before.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

注意:我只是解决你的引用问题,我不保证你的命令会实现你的意图。

相关内容