bash,遍历同一个文件以找到孩子

bash, Traverse to same file to find the childs

我有以下格式的数据

1234|4568
4568|abcd
abcd|0987
pqrs|1111
0987|2222
lmno|xyza

预期输出是

1234|2222
pqrs|1111
lmno|xyza

它的匹配方式是为每条记录找到它的 childs & subchild 并采用 parent

的最低 child 条目

a|b
b|c
c|d

因此此类条目所需的输出是

a|d

也有可能

a|b
b|a

其中 a|a 将是输出

我很困惑我怎么能得到这个?[花了几个小时思考如何做到这一点?] 我可以在 AWK 中使用关联数组吗?

不是完整的解决方案,但也许可以帮助您入门...

$ awk -F"|" '{a[]=} 
          END{for(i in a) 
                {k=a[i]; 
                 printf i"/"k; 
                 while (k in a) {k=a[k]; printf "/"k}
                 print ""
                }
             }' file
abcd/0987/2222
4568/abcd/0987/2222
1234/4568/abcd/0987/2222
0987/2222
lmno/xyza
pqrs/1111

会给你路径。您需要剔除较短的子序列并添加循环检测。

这一班轮做你想要的:

awk -F'|' -v OFS='|' '{for(x in a)if(a[x]==){a[x]=;next}a[]=}
                       END{for(x in a)print x, a[x]}' file

用你的例子测试:

kent$  cat f
1234|4568
4568|abcd
abcd|0987
pqrs|1111
0987|2222
lmno|xyza

kent$  awk -F'|' -v OFS='|' '{for(x in a)if(a[x]==){a[x]=;next}a[]=}END{for(x in a)print x, a[x]}' f
lmno|xyza
pqrs|1111
1234|2222

这可能对你有用 (GNU sed):

sed -r '1h;1!H;$!d;x;:a;s/\|([^\n]+)(.*)\n(\|[^\n]+)//;ta' file

这会将文件插入内存并反复使用模式匹配和替换,直到没有进一步的匹配发生。