例如,我有两个文件:
文件1:
1
4
X
5
X
7
文件2:
2
3
5
X
X
1
我想将X
file1 的 -lines 替换为 file2 中相应行中的内容:
结果:
1
4
5
5
X
7
我更喜欢使用 CLI 命令的解决方案,例如sed
.
答案1
如果 file2 适合内存,那么您可以使用 awk。首先让它读取 file2,然后在处理 file1 时,如果看到“X”,则从 file2 数组中替换它:
$ awk 'NR == FNR { lines[NR]=$0; } NR != FNR { if ($0 == "X") print lines[FNR]; else print $0 }' file2 file1
重新格式化一下,就是:
$ awk 'NR == FNR { lines[NR]=$0; }
NR != FNR { if ($0 == "X") print lines[FNR];
else print $0
}' file2 file1
请注意,file2 是第一个文件名; file1 是第二个文件名。
答案2
$ paste file1 file2 | awk -F '\t' '$1 == "X" { $1 = $2 } { print $1 }'
1
4
5
5
X
7
该paste
命令将生成制表符分隔的输出
1 2
4 3
X 5
5 X
X X
7 1
如果第一个字段是字符,则awk
脚本只需将第一个制表符分隔字段设置为第二个字段的内容X
,然后打印第一个(现在可能已修改)字段。
不同的方法由格伦·杰克曼推荐它不会修改传入的数据,而只是根据第一列中的数据选择要打印的字段:
$ paste file1 file2 | awk -F '\t' '{ print $1 == "X" ? $2 : $1 }'
使用 GNU sed
:
$ paste file1 file2 | sed -E -e '/^X/s/^[^\t]+\t//' -e 's/\t.*$//'
1
4
5
5
X
7
这两个sed
表达式执行以下操作:
- 如果当前行以 开头
X
,则第一次替换将删除第一个制表符之前的所有内容(包括第一个制表符)。paste
如果第一列是 ,这会有效地将输出的第二列移动到第一列X
。 - 第二个表达式删除制表符及其后面的任何内容。这会删除我们不感兴趣的数据。
答案3
用bash
while IFS= read -r -u3 f1; IFS= read -r -u4 f2; do
[[ $f1 == X ]] && echo "$f2" || echo "$f1"
done 3<file1 4<file2
或者更一般地说,POSIX
while IFS= read -r f1 <&3; IFS= read -f f2 <&4; do
[ "$f1" = X ] && echo "$f2" || echo "$f1"
done 3<file1 4<file2