我想编写一个 sed (或 awk)命令来将一个文件中的字符串替换为另一个文件的全部内容

我想编写一个 sed (或 awk)命令来将一个文件中的字符串替换为另一个文件的全部内容

我想编写一个 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;

...但是,输出中会添加一个额外的换行符。您可以使用slurptrim-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

https://raku.org

相关内容