我是 Linux 环境的新手,我需要编写一个脚本来处理一些数据。
我有一个如下所示的文件:
文件A:
1 X 1 1.0
2 X 1 1.0
3 X 1 1.0
4 Y 2 1.0
5 Y 2 1.0
6 Z 3 1.0
另一个文件如下所示:
文件B:
1 0.5
2 0.3
3 0.2
我需要将文件 A 第 4 列中的数字替换为文件 B 第 2 列中出现的数字,但它必须将文件 A 第 3 列中的数字与文件 A 第 1 列中的数字相匹配文件B
所需的输出是:
1 X 1 0.5
2 X 1 0.5
3 X 1 0.5
4 Y 2 0.3
5 Y 2 0.3
6 Z 3 0.2
答案1
如果您无法对文件进行排序,请使用 Awk,它(如join
)是为处理分隔数据而设计的。
在这种情况下,首先传递第二个文件,构建一个查找表,然后在传递第一个文件时使用查找表修改该文件的每一行。
$ cat file2
1 0.5
2 0.3
3 0.2
$ cat file1
1 X 1 1.0
2 X 1 1.0
3 X 1 1.0
4 Y 2 1.0
5 Y 2 1.0
6 Z 3 1.0
$ awk 'NR==FNR {a[$1] = $2; next} {$4 = a[$3]} 1' file2 file1
1 X 1 0.5
2 X 1 0.5
3 X 1 0.5
4 Y 2 0.3
5 Y 2 0.3
6 Z 3 0.2
$
答案2
join -1 3 -o 1.1,1.2,0,2.2 file1 file2
使用提供的文件输出:
$ cat file1
1 X 1 1.0
2 X 1 1.0
3 X 1 1.0
4 Y 2 1.0
5 Y 2 1.0
6 Z 3 1.0
$ cat file2
1 0.5
2 0.3
3 0.2
$ join -1 3 -o 1.1,1.2,0,2.2 file1 file2
1 X 1 0.5
2 X 1 0.5
3 X 1 0.5
4 Y 2 0.3
5 Y 2 0.3
6 Z 3 0.2
$
请注意,两个输入文件都必须排序(针对您希望将它们加入的列)。那是词典编法sort -n
需要排序,而不是数字,因此如果有超过十个项目,请确保对文件进行适当的排序。 (加入后可以再次度假村。)
答案3
如果您无法对输入进行排序,那么join
将无法工作,但您可以使用sed
它。这个想法是使用sed
一次将 fileB 转换为脚本,然后将该脚本反馈回以sed
转换 fileA。
因此,在一行中,使用标准 POSIX shell 命令替换:
sed -e "$(sed 's:^\([0-9]*\) \(.*\)$:s/\1 *[^ ]*$/\1 \2/:' file2)" file1