如何将包含从 X 到 Y 的数字的行插入到 Z 行之后的另一个文件中?

如何将包含从 X 到 Y 的数字的行插入到 Z 行之后的另一个文件中?

我创建了两个文件:

echo -e "1\n2\n3\n4\n5" > 123.txt
echo -e "a\nb\nc\nd\ne" > abc.txt

我想获取123.txt包含以下内容的文件:

1
2
3
b
c
d
4
5

换句话说,将文件中编号为 2 到 4 的行插入abc.txt到文件的123.txt第三行之后。

我在这里查看了许多类似的问题,但没有找到合适的答案。尽管如此,我还是得到了这样的台词:

sed -n '2,4p' abc.txt

并在第三行之后将一些文本放入文件中:

sed -i '3a\mytext' 123.txt

如何使用前面的命令 stdout 或/和sed/awk单个命令来执行此操作?

答案1

如果您的系统有 GNU 版本sed,则可以使用 GNU 扩展r命令:

r filename
    As a GNU extension, this command accepts two addresses.

    Queue the contents of filename to be read and inserted into the
    output stream at the end of the current cycle, or when the next input 
    line is read. Note that if filename cannot be read, it is treated as 
    if it were an empty file, without any error indication.

    As a GNU sed extension, the special value /dev/stdin is supported for 
    the file name, which reads the contents of the standard input. 

例如,

$ sed '3r /dev/stdin' 123.txt < <(sed -n '2,4p' abc.txt)
1
2
3
b
c
d
4
5

答案2

通过使用awksed

$ awk 'FNR==3{print;system("sed -n '2,4p' abc.txt");next};1' 123.txt 
1
2
3
b
c
d
4
5

答案3

通过sed,您可以使用该r命令插入整个文件。要插入文件的一部分,请提取该部分并将其通过管道作为输入到sed.您sed也可以用来进行提取。

sed -n '2,4p' abc.txt | sed -i '3r /dev/stdin' 123.txt

使用awk,您可以读取一个文件并在中间切换到另一个文件。

awk <123.txt >123.txt.new '
    1                                    # print the input line
    NR==3 {                              # after line 3 of 123.txt, …
        while (getline < "abc.txt") {
            ++inner_NR;
            if (inner_NR >= 2) print;    # start printing at line 2 from abc.txt
            if (inner_NR == 4) break;    # stop after line 4
        }
    }
' &&
mv 123.txt.new 123.txt

您还可以使用headtail来提取要合并的文件部分。

head -n 3 <123.txt >123.txt.new &&
<abc.txt tail -n +2 | head -n 3 >>123.txt.new &&
tail -n +4 123.txt >>123.txt.new &&
mv 123.txt.new 123.txt

您可以将head+tail方法与结合起来sed。对于大文件,这可能是最快的。

<abc.txt tail -n +2 | head -n 3 | sed -i '3r /dev/stdin' 123.txt

请注意,所有这些方法都会写入移动到的临时文件123.txt(甚至使用 的方法sed -i,因为这就是sed -i幕后的操作)。

答案4

ed使用和进行就地编辑sed(在 bash 提示符下):

ed -s 123.txt<<<$'3r !sed -n "2,4p" abc.txt\nw'

相关内容