我创建了两个文件:
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
通过使用awk
和sed
:
$ 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
您还可以使用head
和tail
来提取要合并的文件部分。
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'