在 ab 子串中搜索 a 并替换 b

在 ab 子串中搜索 a 并替换 b

我的 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) 将文件读取为无标头的“漂亮打印”数据,然后在文件hostsnew文件之间执行左连接操作,使用每行上的第二个和第三个字段作为连接键。

$ 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

相关内容