bash 删除重复的键值并保留顺序

Sur*_*ran 1 bash awk

我有 2 个文件需要合并并生成第 3 个文件。请在下面找到示例,

文件 1

xab=p11
aab=p12
aac=p23
xac=p15
yab=p16
Run Code Online (Sandbox Code Playgroud)

档案 2

aab=p17
xac=p25
yyc=p22
Run Code Online (Sandbox Code Playgroud)

我想保留第一个文件的顺序并附加第二个文件。结果应该是:

文件 3

xab=p11
aab=p17
aac=p23
xac=p25
yab=p16
yyc=p22
Run Code Online (Sandbox Code Playgroud)

我尝试了很多方法,但无法获得更简单、易于理解的解决方案。我在 StackOverflow 中找到的那个是有效的,但很难理解并向第三者解释。我找到的解决方案是

cat en_us.txt en_US2.txt | tr -s '\n' | awk -F= '!a[$1]{b[++i]=$1} {a[$1]=$0;} END{for(j=1;j<=i;j++){print a[b[j]]}}'
Run Code Online (Sandbox Code Playgroud)

任何人都可以尝试这个并获得一个可读的解决方案(可能没有使用awk

Sun*_*eep 9

另一种awk解决方案:

$ awk -F'=' '{ if($1 in b) a[b[$1]]=$0;
               else{a[++i]=$0; b[$1]=i} }
             END{for(j=1;j<=i;j++) print a[j]}' f1 f2
xab=p11
aab=p17
aac=p23
xac=p25
yab=p16
yyc=p22
Run Code Online (Sandbox Code Playgroud)
  • 请注意,这两个文件在此处作为单个输入一起处理,没有任何NR==FNR内容
  • else{a[++i]=$0; b[$1]=i} 如果之前未看到第一列,则执行此代码
    • a[++i]=$0 这将根据数字键保存行内容
    • b[$1]=i 此数组有助于根据第一列获取数字键编号
  • if($1 in b) a[b[$1]]=$0 当第一列已经存在时执行
    • a[b[$1]]=$0 这将更新较早的条目
  • END{for(j=1;j<=i;j++) print a[j]} 处理完所有输入行后打印数组内容

使用ruby,因为默认情况下保留插入顺序,所以更容易。

$ ruby -F'=' -lane 'BEGIN{h={}}; h[$F[0]]=$_; END{puts h.values}' f1 f2
xab=p11
aab=p17
aac=p23
xac=p25
yab=p16
yyc=p22
Run Code Online (Sandbox Code Playgroud)
  • BEGIN{h={}};将空分配hash给变量h
  • h[$F[0]]=$_ 根据第一个字段保存输入行的内容
  • puts h.values打印每个hash键的值

您可以通过使用h[$F[0]]=$F[1]然后节省一些空间END{h.each_key{|k| puts "#{k}=#{h[k]}"}}