【问题标题】:sed read entire lines from one file and replace lines in another filesed 从一个文件中读取整行并替换另一个文件中的行
【发布时间】:2020-11-19 17:17:50
【问题描述】:

我有两个文件:file1,文件内容如下:

文件1:

f1 line1
f1 line2
f1 line3

文件2:

f2 line1
f2 line2
f2 line3
f2 line4

想知道如何使用 sed 从文件 1 中读取第 1 行到第 3 行,并使用这些行将第 2 行替换为文件 2 中的第 3 行。

输出应该是这样的:

f2 line1
f1 line1
f1 line2
f1 line3
f2 line4

有人可以帮忙吗?谢谢,

【问题讨论】:

  • Sed 不是这项工作的正确工具。你可以做到,但这就像用刀钉钉子一样。
  • 您有更好的建议吗?谢谢
  • 是的,awk 会是更好的选择。

标签: sed replace


【解决方案1】:

如果你有支持s///e的GNU sed,你可以使用e来调用head -n3 file1

我认为(尚未测试):

sed '2d;3s/.*/head -n3 file1/e' file2

我去验证一下……

【讨论】:

  • 谢谢。这行得通。但是你能解释一下在这种情况下“s///e”的用法吗?
  • 'e' 正在 shell 中执行模式缓冲区的内容......所以s/.*/echo test/e 将删除整行,将echo test 命令脱壳,然后从@ 插入标准输出987654327@ 在输出中。所以,s/.*/echo test/e 等价于d;a test ...标准输出不会返回到模式缓冲区中。
  • 也可能等同于d; e echo test ... e 不一定是s///e 的一部分。它只是比裸 e 更灵活
【解决方案2】:

sed 是对单个字符串执行s/old/new 的最佳工具。这不是你想要做的,所以你不应该考虑尝试使用 sed 。在每个 UNIX 机器上的任何 shell 中使用任何 awk:

$ cat tst.awk
NR==FNR {
    if ( FNR <= num ) {
        new = new $0 ORS
    }
    next
}
(beg <= FNR) && (FNR <= end) {
    if ( !done++ ) {
        printf "%s", new
    }
    next
}
{ print }

.

$ awk -v num=3 -v beg=2 -v end=3 -f tst.awk file1 file2
f2 line1
f1 line1
f1 line2
f1 line3
f2 line4

要从 file1 中读取不同数量的行,只需更改 num 的值,要使用 file2 中不同范围的行的替换文本,只需更改 begend 的值。因此,例如,如果您想使用管道中的 10 行数据(例如 seq 15 |)而不是 file1,并且想要像您一样在 file2 的第 3 行和第 17 行之间替换,但使用 20 行而不是 4 行,那么您'd 将 awk 脚本保持原样,然后调整你的调用方式:

$ seq 15 | awk -v num=10 -v beg=3 -v end=17 -f tst.awk - file2
f2 line1
f2 line2
1
2
3
4
5
6
7
8
9
10
f2 line18
f2 line19
f2 line20

尝试对 sed 进行同样的操作,以便对需求进行如此细微的更改,并注意您是如何更改脚本的,并且它不能移植到其他 sed 版本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-12
    • 1970-01-01
    • 1970-01-01
    • 2011-09-22
    • 2021-04-26
    • 1970-01-01
    • 1970-01-01
    • 2021-10-04
    相关资源
    最近更新 更多