sum*_*ess 2 bash awk text-processing
我在文本文件中有以下数据集:
文件1.txt
a1:b1
a2:b2
a3:b3
a4:b4
a5:b5
Run Code Online (Sandbox Code Playgroud)
文件2.txt
b2:c1
b4:c2
b5:c3
Run Code Online (Sandbox Code Playgroud)
如何合并这些值以制作这样的输出文件:
输出.txt
a2:c1
a4:c2
a5:c3
Run Code Online (Sandbox Code Playgroud)
由于您的文件似乎包含已排序的数据,您应该能够使用join命令,例如
join -12 -21 -t: -o1.1,2.2 file1.txt file2.txt > output.txt
Run Code Online (Sandbox Code Playgroud)
然后
cat output.txt
a2:c1
a4:c2
a5:c3
Run Code Online (Sandbox Code Playgroud)
有关man join选项的详细信息,请参阅。
如果文件没有预先排序,那么您可以先使用进程替换对它们进行排序。但是请注意,排序必须在您要加入文件的字段上,例如
join -12 -21 -t: -o1.1,2.2 <(sort -t: -k2,2 file1.txt) <(sort -k1,1 file2.txt)
androgynous:hu2nt
gra7vel:fi6nal
cosm4etic:citizen
Run Code Online (Sandbox Code Playgroud)
结果也将按排序顺序排列:如果您不想要那样,那么有一种相当标准的方法可以awk使用数组来执行此类操作,例如
awk -F: 'NR==FNR {a[$2]=$1; next;} ($1 in a) {print a[$1]":"$2;}' file1.txt file2.txt
Run Code Online (Sandbox Code Playgroud)
这是一种awk方法:
awk -F: '(NR==FNR){a[$2]=$1; next}($1 in a){print a[$1]":"$2};' file1 file2 > out
Run Code Online (Sandbox Code Playgroud)
awk -F:运行awk,将字段分隔符设置为:. 这将读取每个输入行并将其拆分为:. 因此,对于 的第一行file1,第一个字段 ( $1) 是a1,第二个字段( $2) 是b1。(NR==FNR){}: 如果NR等于FNR。NR是当前输入行号,FNR是当前文件的行号。只有在读取第一个文件时,两者才会相等。a[$2]=$1; next: 将第二个字段保存为数组中a的键,其值为第一个字段。然后,跳到下一行。($1 in a){print a[$1]":"$2}: 这只会在读取第二个文件时执行。如果第二个文件的第一个字段是键数组a,则打印该键的值(来自 的相应行的第二个字段file1)。还有一个 Perl:
perl -F: -lanE '$k{$F[0]} ? say "$k{$F[0]}:$F[1]" : ($k{$F[1]}=$F[0]);' file1 file2 > out
Run Code Online (Sandbox Code Playgroud)
或者,如果您更喜欢:
perl -F: -lanE '$k{$F[0]} and say "$k{$F[0]}:$F[1]" or ($k{$F[1]}=$F[0]);' file1 file2
Run Code Online (Sandbox Code Playgroud)
perl -F: -lanE:-n意思是“逐行读取每个输入文件并将给定的脚本应用-E到每个文件”。-E,像-e,让您在命令行上传递脚本。不同之处在于-E启用了一些额外的功能,例如say. 在-a使上由给定的字符每个输入行的自动分割-F。在一起,他们使perl行为很像awk。字段被分成数组@F,第一个字段是$F[0],第二个$F[1]等等。最后,从每行的末尾-l去除换行符 ( \n) 字符。$k{$F[0]} ? foo : bar: 如果变量$k{$F[0]}已定义,则执行 foo,否则执行 bar。($k{$F[1]}=$F[0]):如果$k{$F[0]}未定义,则会发生这种情况(它是上面的“条”)。它将第二个字段保存为哈希中%k的键,其值为第一个字段。say "$k{$F[0]}:$F[1]":如果$k{$F[0]}已定义(上面的“foo”),这将运行,因此如果当前行的第一个字段是另一行中的第二个字段。如果是,则打印(say就像print但添加换行符)当前的第一个字段以及散列中与其关联的值。