使用命令行实用程序执行以下地图更新

Using a command-line utility to perform the following map-updates

我是使用命令行实用程序的完全新手,想知道如何按以下方式处理信息:

mapping.txt:

80  001 002
81  011 012 013 014
82  021 022
...

input.txt:

81  103823044
80  103823054
81  103823064
...

想要output.txt

103823044|011|
103823044|012|
103823044|013|
103823044|014|
103823054|001|
103823054|002|
103823064|011|
103823064|012|
103823064|013|
103823064|014|

我已经完成了简单的映射,其中列号是固定的,但我不确定如何将动态数量的列映射到所需的输出

如果顺序不重要,join 和 awk 可以轻松完成。

$ join <(sort input.txt) <(sort mapping.txt) | awk -v OFS="|" '{for (i=3;i<NF;i++) print , $i OFS}'
103823054|001|
103823044|011|
103823044|012|
103823044|013|
103823064|011|
103823064|012|
103823064|013|

这是一个 GNU awk 脚本,它使用多维数组来执行您想要的操作:

#!/usr/bin/awk -f

BEGIN { OFS="|" }

FNR==NR { for(i=2;i<=NF;i++) a[][$i]; next }

 in a { for(k in a[]) print , k, "" }

如果您将其保存到 script.awk 这样的文件中,然后 chmod +x script.awk 您可以 运行 像这样:

$ ./script.awk mapping.txt input.txt
103823044|011|
103823044|012|
103823044|013|
103823044|014|
103823054|002|
103823054|001|
103823064|011|
103823064|012|
103823064|013|
103823064|014|

这是脚本的细分:

  • BEGIN - 将输出字段分隔符设置为 |
  • FNR==NR - 处理第一个文件(mapping.txt)并先按</code>,然后按其他字段将数据存储在多维数组中。 <code>next 跳过任何其他行处理。
  • in a - 测试该行是否有映射。如果是这样,请按顺序打印出相应的映射(也是 GNU awk)。 print 命令中的逗号被转换为 OFS 值。

它可以重新制作成 "one-liner",例如:

awk -v OFS="|" 'FNR==NR {for(i=2;i<=NF;i++) a[][$i]; next}  in a {for(k in a[]) print , k, ""}' mapping.txt input.txt

这是使用一维数组存储 [=25=] 然后 split() 稍后保存顺序的脚本版本:

#!/usr/bin/awk -f

BEGIN { OFS="|" }

FNR==NR { a[]=[=13=]; next }

 in a { c=split(a[], b); for(i=2;i<=c;i++) print , b[i], "" }