免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 2074 | 回复: 17
打印 上一主题 下一主题

[文本处理] 用shell / awk / sed能实现级联树状结构么 [复制链接]

论坛徽章:
2
技术图书徽章
日期:2013-12-17 13:52:152015亚冠之萨济拖拉机
日期:2015-07-19 11:07:52
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-08-31 21:52 |只看该作者 |倒序浏览
比如下面的文件


  1. id pid name
  2. 2 1 d
  3. 1 0 a
  4. 3 1 b
  5. 4 2 c
  6. 5 3 e
复制代码


id是不重复的,pid是parent的id,要求遍历所有的父子节点,实现如下的输出,用shell 或者awk / sed适合么?


  1. 0->1->2->4 a,d,c
  2. 0->1->3->5 a,b,e
复制代码

论坛徽章:
145
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07子鼠
日期:2013-11-18 18:48:57白羊座
日期:2013-11-29 10:09:11狮子座
日期:2013-12-12 09:57:42白羊座
日期:2013-12-24 16:24:46辰龙
日期:2014-01-08 15:26:12技术图书徽章
日期:2014-01-17 13:24:40巳蛇
日期:2014-02-18 14:32:59未羊
日期:2014-02-20 14:12:13白羊座
日期:2014-02-26 12:06:59
2 [报告]
发表于 2016-08-31 23:55 |只看该作者
回复 1# rm-rf


$ cat FILE

id pid name
2 1 d
1 0 a
3 1 b
4 2 c
5 3 e
6 2 g
7 1 x
8 7 j
9 7 k
10 9 m
12 3 f

$ awk 'function child(v,cs,as,x){if(c[v]==""){sub(",$","",as);print cs v,as;return}while(x=index(c[v]," ")){cx=substr(c[v],1,x-1);child(cx,cs v"->",as a[v,cx]",");c[v]=substr(c[v],x+1)}child(c[v],cs v"->",as a[v,c[v]]",")}/^[0-9]/{c[$2]=c[$2]d[$2]$1;d[$2]=" ";a[$2,$1]=$3}END{child(0)}' FILE
0->1->2->4 a,d,c
0->1->2->6 a,d,g
0->1->3->5 a,b,e
0->1->3->12 a,b,f
0->1->7->8 a,x,j
0->1->7->9->10 a,x,k,m

论坛徽章:
307
程序设计版块每周发帖之星
日期:2016-04-08 00:41:33操作系统版块每日发帖之星
日期:2015-09-02 06:20:00每日论坛发贴之星
日期:2015-09-02 06:20:00程序设计版块每日发帖之星
日期:2015-09-04 06:20:00每日论坛发贴之星
日期:2015-09-04 06:20:00每周论坛发贴之星
日期:2015-09-06 22:22:00程序设计版块每日发帖之星
日期:2015-09-09 06:20:00程序设计版块每日发帖之星
日期:2015-09-19 06:20:00程序设计版块每日发帖之星
日期:2015-09-20 06:20:00每日论坛发贴之星
日期:2015-09-20 06:20:00程序设计版块每日发帖之星
日期:2015-09-22 06:20:00程序设计版块每日发帖之星
日期:2015-09-24 06:20:00
3 [报告]
发表于 2016-09-01 02:10 |只看该作者
找了一条引用链:
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;

  4. readline;
  5. my @aVals = map {[split]} <>;
  6. my ($id, $pid, $name) = @{$aVals[0]};
  7. while (grep {$id == $aVals[$_][1] ? do {($id, $pid, $name) = @{$aVals[$_]}; 1} : 0} 1 .. $#aVals){}
  8. my ($offset, @aData);
  9. unshift (@{$aData[0]}, $id);
  10. unshift (@{$aData[1]}, $name);
  11. while (grep {$pid == $aVals[$_][0] ? do {$offset = $_; 1} : 0} 0 .. $#aVals){
  12.     ($id, $pid, $name) = @{$aVals[$offset]};
  13.     unshift (@{$aData[0]}, $id);
  14.     unshift (@{$aData[1]}, $name);
  15. }

  16. print join ("->", $pid, @{$aData[0]}), "\t", join (",", @{$aData[1]}), "\n";
复制代码

perl abc.pl a
---------------------------------------------------
0->1->2->4      a,d,c

论坛徽章:
307
程序设计版块每周发帖之星
日期:2016-04-08 00:41:33操作系统版块每日发帖之星
日期:2015-09-02 06:20:00每日论坛发贴之星
日期:2015-09-02 06:20:00程序设计版块每日发帖之星
日期:2015-09-04 06:20:00每日论坛发贴之星
日期:2015-09-04 06:20:00每周论坛发贴之星
日期:2015-09-06 22:22:00程序设计版块每日发帖之星
日期:2015-09-09 06:20:00程序设计版块每日发帖之星
日期:2015-09-19 06:20:00程序设计版块每日发帖之星
日期:2015-09-20 06:20:00每日论坛发贴之星
日期:2015-09-20 06:20:00程序设计版块每日发帖之星
日期:2015-09-22 06:20:00程序设计版块每日发帖之星
日期:2015-09-24 06:20:00
4 [报告]
发表于 2016-09-01 02:33 |只看该作者
本帖最后由 sunzhiguolu 于 2016-09-01 02:55 编辑

  理解的有偏差,,,


   





论坛徽章:
6
15-16赛季CBA联赛之新疆
日期:2016-03-22 22:34:5915-16赛季CBA联赛之山东
日期:2016-04-11 09:08:41程序设计版块每日发帖之星
日期:2016-06-28 06:20:00程序设计版块每日发帖之星
日期:2016-07-19 06:20:00每日论坛发贴之星
日期:2016-07-19 06:20:0015-16赛季CBA联赛之青岛
日期:2016-07-20 22:44:17
5 [报告]
发表于 2016-09-01 06:10 |只看该作者
$_ = do {$/=undef; <>};        #read file
s/^.+\n//;        #remove header
s/^(\d+) (\d+) /$2->$1 /gm;                #-> relationship
$tree = $_;        #keep a copy of relationship
1 while (s/^([1-9]\d*)->(.+?) /($id, $v) = ($1,$2);  $tree =~ m:^(.+)->$id (\w+):m;  "$1->$id->$v $2,"/mge);        #create a full list
for $i ($tree =~ /^(\d+)/mg ) { s/^.+->$i .+\n//gm };  #remove lines ends with pids
print;

_____
$>  cat aa|perl aa.pl
0->1->2->4 a,d,c
0->1->3->5 a,b,e
0->1->2->6 a,d,g
0->1->7->8 a,x,j
0->1->7->9->10 a,x,k,m
0->1->3->12 a,b,f

论坛徽章:
2
技术图书徽章
日期:2013-12-17 13:52:152015亚冠之萨济拖拉机
日期:2015-07-19 11:07:52
6 [报告]
发表于 2016-09-01 10:48 |只看该作者
回复 2# jason680

太给力了,超赞!

论坛徽章:
2
射手座
日期:2014-10-10 15:59:4715-16赛季CBA联赛之上海
日期:2016-03-03 10:27:14
7 [报告]
发表于 2016-09-01 11:34 |只看该作者
回复 1# rm-rf


  1. echo 'id pid name
  2. 2 1 d
  3. 1 0 a
  4. 3 1 b
  5. 4 2 c
  6. 5 3 e'|awk '
  7. function ss(x,l,n,t){
  8.   if(length(a[x])){
  9.     l=l?l"->"x:x
  10.         t = n
  11.     for(j in a[x]){
  12.       n=n?n","a[x][j]:a[x][j]
  13.       ss(j,l,n,t)
  14.           n=t
  15.     }
  16.   }else{
  17.     print l"->"x, n;
  18.         l=n=""
  19.   }
  20. }
  21. NR>1{a[$2][$1]=$3}
  22. END{for(i in a){ss(i,"","","")}}
  23. '
  24. 0->1->2->4 a,d,c
  25. 0->1->3->5 a,b,e
  26. 1->2->4 d,c
  27. 1->3->5 b,e
  28. 2->4 c
  29. 3->5 e
复制代码

论坛徽章:
2
技术图书徽章
日期:2013-12-17 13:52:152015亚冠之萨济拖拉机
日期:2015-07-19 11:07:52
8 [报告]
发表于 2016-09-01 22:31 |只看该作者
回复 2# jason680

大侠,这个脚本非常经典,感谢。能更加一步,判断里面的cycle么?比如出现cycle只打印第一次遍历出来的即可


  1. id pid name
  2. 2 1 d
  3. 1 0 a
  4. 3 1 b
  5. 4 2 c
  6. 9 10 p
  7. 5 3 e
  8. 6 2 g
  9. 7 1 x
  10. 8 7 j
  11. 9 7 k
  12. 2 6 m
  13. 12 3 f
复制代码
结果为:

  1. 0->1->2->4 a,d,c
  2. 0->1->2->6 a,d,g
  3. 0->1->3->5 a,b,e
  4. 0->1->3->12 a,b,f
  5. 0->1->7->8 a,x,j
  6. 0->1->7->9 a,x,k
复制代码
其中0->1->2->6这个链表cycle了,只打印第一次遍历到的情况

论坛徽章:
6
15-16赛季CBA联赛之新疆
日期:2016-03-22 22:34:5915-16赛季CBA联赛之山东
日期:2016-04-11 09:08:41程序设计版块每日发帖之星
日期:2016-06-28 06:20:00程序设计版块每日发帖之星
日期:2016-07-19 06:20:00每日论坛发贴之星
日期:2016-07-19 06:20:0015-16赛季CBA联赛之青岛
日期:2016-07-20 22:44:17
9 [报告]
发表于 2016-09-01 23:05 |只看该作者
$>  cat bb|perl aa.pl
0->1->2->4 a,d,c
0->1->3->5 a,b,e
0->1->7->8 a,x,j
0->1->7->9 a,x,k
0->1->3->12 a,b,f
$>  cat aa.pl
$_ = do {$/=undef; <>}; #read file
s/^.+\n//;      #remove header
s/^(\d+) (\d+) /$2->$1 /gm;             #-> relationship
$tree = $_;     #keep a copy of relationship
while (s/^([1-9]\d*)->(.+?) /($id, $v) = ($1,$2);  $tree =~ m:^(.+)->$id (\w+):m;  "$1->$id->$v $2,"/mge)       #create a full list
{
  s/.*(\d+)->.*\1.+\n//; #Remove cycles
}
for $i ($tree =~ /^(\d+)/mg ) { s/^.+->$i .+\n//gm };  #remove lines ends with pids
print;

论坛徽章:
145
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07子鼠
日期:2013-11-18 18:48:57白羊座
日期:2013-11-29 10:09:11狮子座
日期:2013-12-12 09:57:42白羊座
日期:2013-12-24 16:24:46辰龙
日期:2014-01-08 15:26:12技术图书徽章
日期:2014-01-17 13:24:40巳蛇
日期:2014-02-18 14:32:59未羊
日期:2014-02-20 14:12:13白羊座
日期:2014-02-26 12:06:59
10 [报告]
发表于 2016-09-02 10:17 |只看该作者
本帖最后由 jason680 于 2016-09-02 10:27 编辑

回复 8# rm-rf

It's hard to know what's happened

"id是不重复的pid是parent的id..."

id pid name
2 1 d
6 2 g
2 6 m

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP