我的 Linux 机器上有一个非常大的主机文件:
1.1.1.1 hostA hosta
1.1.1.2 hostB hostb
1.1.1.3 hostC hostc
1.1.1.4 hostD hostd
1.1.1.5 hostE hoste
1.1.1.6 hostF hostf
1.1.1.7 hostG hostg
.......
我有我想修改的行file2
:
2.1.1.1 hostA hosta
2.1.1.2 hostB hostb
2.1.1.3 hostC hostc
因此,期望的输出是:
2.1.1.1 hostA hosta
2.1.1.2 hostB hostb
2.1.1.3 hostC hostc
1.1.1.4 hostD hostd
1.1.1.5 hostE hoste
1.1.1.6 hostF hostf
1.1.1.7 hostG hostg
.......
我知道如何使用,如下所示:
sed '/hostA/ s/1.1.1.1/2.1.1.1/' hosts
但我不知道如何在for
循环中使用它。或者还有另一种更快的方法来修改主机?
答案1
以下是使用磨坊主( mlr
) 将文件读取为无标头的“漂亮打印”数据,然后在文件hosts
与new
文件之间执行左连接操作,使用每行上的第二个和第三个字段作为连接键。
$ mlr --pprint -N join -j 2,3 -f hosts --ul then reorder -f 1,2,3 new
2.1.1.1 hostA hosta
2.1.1.2 hostB hostb
2.1.1.3 hostC hostc
1.1.1.4 hostD hostd
1.1.1.5 hostE hoste
1.1.1.6 hostF hostf
1.1.1.7 hostG hostg
reorder
最后的操作按照在输入中找到的相同顺序对字段重新排序(否则我们会将最后两个字段作为部分数据的字段 1 和 2)。
答案2
您可以使用 2 个 GNU sed 调用来完成此操作,例如:
sed -E 's:([^ ]+) +(.*):/\2/ s/^[^ ]+/\1/:' file2 |
sed -Ef - hosts
第一个sed
生成一个新的 sed 脚本:
/hostA hosta/ s/^[^ ]+/2.1.1.1/
/hostB hostb/ s/^[^ ]+/2.1.1.2/
/hostC hostc/ s/^[^ ]+/2.1.1.3/
答案3
使用任何 awk:
$ awk 'NR==FNR{ip[$2]=$1; next} $2 in ip{$1=ip[$2]} 1' file2 hosts
2.1.1.1 hostA hosta
2.1.1.2 hostB hostb
2.1.1.3 hostC hostc
1.1.1.4 hostD hostd
1.1.1.5 hostE hoste
1.1.1.6 hostF hostf
1.1.1.7 hostG hostg
或者如果您关心保留字段之间的空白:
awk 'NR==FNR{ip[$2]=$1; next} $2 in ip{sub(/[0-9.]+/,ip[$2])} 1' file2 hosts
如果您实际上需要使用每行中的两个主机名作为键,而不是$2
像示例中那样,那么只需将 every 更改$2
为($2,$3)
.
答案4
作为一个变体:
$ cut -d' ' -f2 file2 > hostids
$ grep -v -f hostids hosts > newhosts
$ cat file2 >> newhosts
$ sort -t' ' -k2 newhosts > hosts