我想编写一个 sed (或 awk)命令来将一个文件中的字符串替换为另一个文件的全部内容。请注意,我想要从中获取内容的第二个文件有多于一行。
$ cat file.txt
TEXT1
TEST2
TEST3
和
$ cat other_file.txt
there are multiple lines1
there are multiple lines2
there are multiple lines3
我希望输出是:
$ cat file3.txt
there are TEXT1
TEST2
TEST3 lines1
there are TEXT1
TEST2
TEST3 lines2
there are TEXT1
TEST2
TEST3 lines3
我试过这个:
sed -i -e '/PLACEHOLDER/ r file' -e s/PLACEHOLDER// otherFile
但它没有给我正确的输出。
将“多个”关键字替换为每行文件中的所有内容希望这一点很清楚
答案1
使用m4
宏处理器,定义一个名为的宏PLACEHOLDER
,其中包含另一个文件:
$ cat file
foo PLACEHOLDER baz
$ cat otherfile
These are the
multi-line contents
of the other file.
$ m4 -D PLACEHOLDER='include(otherfile)' file
foo These are the
multi-line contents
of the other file.
baz
请注意,这包括原样的文本otherfile
,而不删除最后的换行符。
答案2
在每个 Unix 机器上的任何 shell 中使用任何 awk,并给出 1 种可能的需求解释(您想要对空格分隔的“单词”进行全字字符串匹配,替换文本可能包含反向引用元字符或其他通常有问题的字符,不关心保留空格,并且目标单词可能在一行中出现多次):
$ cat tst.awk
BEGIN {
ORS = RS RS
old = "multiple"
}
NR==FNR {
new = (NR>1 ? new RS : "") $0
next
}
{
for ( i=1; i<=NF; i++ ) {
if ( $i == old ) {
$i = new
}
}
print
}
$ awk -f tst.awk file.txt other_file.txt
there are TEXT1
TEST2
TEST3 lines1
there are TEXT1
TEST2
TEST3 lines2
there are TEXT1
TEST2
TEST3 lines3
答案3
使用乐(以前称为 Perl_6)
~$ raku -e 'my @a = dir(test => "Matsuo_Bashō.txt").IO.lines.join("\n"); for lines[0..9] { put S/e/@a[]/ };' alphabet.txt
a
b
c
d
No one travels
Along this way but I,
This autumn evening.
f
g
h
i
j
Original_File 被替换==alphabet.txt
~$ raku -e 'for lines[0..9] { .put };' alphabet.txt
a
b
c
d
e
f
g
h
i
j
要插入的第二个文件==Matsuo_Bashō.txt
~$ raku -e 'put dir(test => "Matsuo_Bashō.txt").IO.lines.join("\n");'
No one travels
Along this way but I,
This autumn evening.
简而言之,获取要“插入”的文件并使用 Raku 的dir()
例程读取它,并将其存储在@a
数组中。然后从命令行读入第二个“目标”文件(此处为字母顺序)。当用S///
“big-S”替换运算符替换时,Raku 将输出结果字符串。注意:上面的代码只会替换第一次出现的代码。要使其成为全局替换(替换所有出现的识别序列 )e
,请添加:global
副词:S:global///
或更简单地说,S:g///
。
替换中不需要反斜杠@a
,只需在末尾添加索引方括号即可:(@a[]
花括号也可以,请参见下文)。
如果您不想替换,而是想在第一个文件中的识别序列之后插入第二个文件,请将替换运算符更改为使用后向断言,并在替换之前添加换行符:
{ put S/ <?after e> /\n@a[]/ }
#OR
{ put S/ <?after e> /\n{@a}/ }
最后请注意,文件可以slurp
一次全部编辑。使用 Raku 的dir()
例程是:
dir(test => "Matsuo_Bashō.txt").IO.slurp;
...但是,输出中会添加一个额外的换行符。您可以使用slurp
和trim-trailing
来复制上面的答案(下面,引用dir()
文件名字符串的简写方式是将其括在尖括号中):
~$ raku -e 'my @a = dir(:test<Matsuo_Bashō.txt>).IO.slurp; for lines[0..9] { put S/e/{@a[].trim-trailing}/ };' alphabet.txt