【发布时间】:2017-01-12 17:03:09
【问题描述】:
我有一种情况,我想用另一个文件中的相应行替换一个大文件的第 4 行,从第 1 行开始(所以第 1、5、9 行等)。
我尝试过使用 sed,但不知道如何使用第二个文件的每 4 行作为替换的输入。
到目前为止我有:
sed '1~4 s/.*/?/' original-file.txt > output-file.txt
我可以用什么来代替“?”正确替换行?
非常感谢任何帮助!
【问题讨论】:
我有一种情况,我想用另一个文件中的相应行替换一个大文件的第 4 行,从第 1 行开始(所以第 1、5、9 行等)。
我尝试过使用 sed,但不知道如何使用第二个文件的每 4 行作为替换的输入。
到目前为止我有:
sed '1~4 s/.*/?/' original-file.txt > output-file.txt
我可以用什么来代替“?”正确替换行?
非常感谢任何帮助!
【问题讨论】:
每当我看到不只是简单思考的事情时,我就会从脑海中删除sed,并尝试使用awk 来做。可能我也是awk-biased,但我确实认为它存储数据和访问行号的方式比sed 更好,更容易理解。
所以,让我们使用the FNR==NR trick 检查一个文件,然后检查另一个:
awk 'FNR==NR {data[FNR]=$0; next} # store data from file 1
(FNR%4==1){ # in file 2, if line number is (4k + 1)
$0=data[FNR] # replace with the same line from the 1st file
}1' file1 file2 # print the line
这里的关键是将文件1中的所有数据存储在数组data[]中,每行的索引为其行号。
那么,在读取文件2时,如果文件1的编号是4的倍数,则将一行替换为文件1的对应行。
查看一个示例,其中包含从 100 到 110 的序列,其中数字从 1 到 10 交错:
$ awk 'FNR==NR {data[FNR]=$0; next} (FNR%4==1){$0=data[FNR]}1' <(seq 10) <(seq 100 110)
1
101
102
103
5
105
106
107
9
109
110
【讨论】:
sed 命令虽然适用于第 1、5、9、13 行等
FNR%4==1 应该可以。让我们看看 OP 更新了什么。
如果你不介意使用 perl,这里有一个小脚本
#!/usr/bin/perl
open my $fh1,'<','original-file.txt' or die;
open my $fh2,'<','other-file.txt' or die;
open my $out,'>','output-file.txt' or die;
my $n=0;
while (<$fh1>) {
my $s=<$fh2>;
print $out ($n++ % 4 == 0 ? $s : $_);
}
这将避免将数据加载到内存中,从而在常量内存中进行操作。
【讨论】:
这可能对你有用(GNU sed):
sed '1~4!d' file2 | sed $'1~4{R/dev/stdin\n;d}' file1 > outFile
这使用了 2 次 sed 调用,并使用文件名 /dev/stdin 将第一次的结果通过管道传输到第二次。还使用 bashes $'...' 在第二次调用中插入换行符。
【讨论】: