假设我有一个文本文件,我想用 中包含的另一个字符串text.txt
替换 中 中包含的(多行)字符串,我该怎么做? (我不想使用正则表达式,我实际上想用中包含的文本替换 中包含的字符串。before.txt
after.txt
before.txt
after.txt
text.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.\n
intext.txt
和text\n
in 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
注意:我只是解决你的引用问题,我不保证你的命令会实现你的意图。