在 bash 中连接和操作 tree-like 结构

Concatenate and manipulate tree-like structure in bash

目前,我有一个命令以下列格式输出数据:

apple: banana
apple: cantaloupe
apple: durian
apple: eggplant
banana: cantaloupe
banana: durian
durian: eggplant
eggplant:

换句话说,它是以apple为根的tree-like结构,有childrenbananaeggplantbanana还有sub-childrencantaloupedurianeggplant 没有 children,但仍有尾随冒号。

我想将输出连接成这种格式:

apple: banana eggplant
banana: cantaloupe durian
durian: eggplant
eggplant:

一些 objects 可能在输出中出现不止一次(在这种情况下,cantaloupedurianeggplant 有多个 parent节点)。虽然这个例子没有,但也可能有多个根节点(即宽度与 apple 相同)。

我将如何修改这个输出?我现在一般使用 bash/shell 脚本,所以我想 awk 可能是处理这个问题的最佳方式,但如果在 Python、[=44 中处理得更好的话=]、Perl 或其他一些脚本语言,我也乐于接受建议。

你可以使用 awk:

awk -F ': *' '{a[] = (a[]? a[] OFS  : )}
       END { for (i in a) print i ": " a[i] }' file
eggplant:
apple: banana cantaloupe durian eggplant
banana: cantaloupe durian
durian: eggplant

保持原来的顺序:

awk -F ': *' '!( in a){b[++n]=} {a[] = (a[]? a[] OFS  : )}
   END{for (i=1; i<=n; i++) print b[i] ": " a[b[i]]}' file
apple: banana cantaloupe durian eggplant
banana: cantaloupe durian
durian: eggplant
eggplant:
awk -F: '{ list[] = list[]  } END { for (i in list) printf "%s:%s\n", i, list[i] }'

使用 awk 中的关联数组累积条目,构建列表。 awk 中的字符串连接有点奇怪。最后,打印出密钥和密钥的条目。如果需要订购,您需要说明。

假设左边的键应该按照在输入的LHS上第一次出现的顺序输出,那么你可以使用这个稍微复杂一点的脚本:

awk -F: '{ if (!( in list)) keys[++n] = ; list[] = list[]  }
         END { for (j = 1; j <= n; j++) printf "%s:%s\n", keys[j], list[keys[j]] }'