免费注册 查看新帖 |

Chinaunix

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

经验介绍:利用gawk扩展的match(s,r,a)功能匹配多个括号 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-01-20 01:08 |只看该作者 |倒序浏览
gawk匹配多个括号,结果放在数组a中,记得以前用过.
现在想一次性将所有匹配到的结果放到数组中,结果只取到一个.
带最后一个*时取到最后一个,不带最后一个*时取到第1个
bash-3.2$ cat match1.xml.awk
echo "<a><c>kjkjkj</c></a><b>jkjk</b><a>jkjk</a><d>dddd</d>
<a><c>kjkjkj</c></a><b>jkjk</b><a>jkjk</a><d>dddd<dd>
aaaaaaaaa44444bbbbbbbb7777777ccccccc99999dddddddd000000"|awk --re-interval '
{
  n=match($0,"(<(/?[^>]+)>([^<]*))*",a);
  i=0;
  for (;i<=n;i++){
    print "a:i="i,"a["i"]="a[ i ],"n="n;
  }
  n=match($0,"(([a-z]*)([0-9]*))*",a);
  i=0;
  for (;i<=n;i++){
    print "b:i="i,"a["i"]="a[ i ],"n="n;
  }
}
'
bash-3.2$  match1.xml.awk
a:i=0 a[0]=<a><c>kjkjkj</c></a><b>jkjk</b><a>jkjk</a><d>dddd</d> n=1
a:i=1 a[1]=</d> n=1
b:i=0 a[0]= n=1
b:i=1 a[1]= n=1
a:i=0 a[0]=<a><c>kjkjkj</c></a><b>jkjk</b><a>jkjk</a><d>dddd<dd> n=1
a:i=1 a[1]=<dd> n=1
b:i=0 a[0]= n=1
b:i=1 a[1]= n=1
a:i=0 a[0]= n=0
b:i=0 a[0]=aaaaaaaaa44444bbbbbbbb7777777ccccccc99999dddddddd000000 n=1
b:i=1 a[1]=dddddddd000000 n=1
bash-3.2$

希望得到的结果:
第1句
a[1]="<a>"
a[2]="a"
a[3]=""
a[4]="<c>kjkjkj"
a[5]="c"
a[6]="kjkjkj"
....
第2句:
a[1]="aaaaaaaaa44444"
a[2]="aaaaaaaaa"
a[3]="44444"
a[4]="bbbbbbbb7777777"
a[5]="bbbbbbbb"
a[6]="7777777"
能实现吗?难道我记错了?
=======================================================================
(以下内容为楼主2009年1月20日新增,同时修改了本贴标题)
谢谢2楼回答,确实只有显式的()个数才算,隐式重复的只算最后一遍的()。
match返回匹配的位置,我错把它当作找到的()个数用了。
这个用法相信对大家是有用的,所以我将正将答案放到顶楼了(条件是有支持GNU extensions,即gawk):

bash-3.2$ cat match1.xml.awk
echo "<a><c>kjkjkj</c></a><b>jkjk</b><a>jkjk</a><d>dddd</d>
aaaaaaaaa44444bbbbbbbb7777777ccccccc99999dddddddd000000"|awk --re-interval '
{
  n=match($0,"(<(/?[^>]+)>([^<]*))+",a);
  if (n>0) {
    print "a:a[0]="a[0],"RSTART="RSTART,"RLENGTH="RLENGTH;
    for (i=1;a[i,"start"]!="";i++){
      print "a:i="i,"a["i"]="a[ i ],"|";
    }
  }
  delete a;
  n=match($0,"(([a-z]*)([0-9]*))+",a);
  if (n>0) {
    print "a:a[0]="a[0],"RSTART="RSTART,"RLENGTH="RLENGTH;
    for (i=1;a[i,"start"]!="";i++){
      print "b:i="i,"a["i"]="a[ i ],"|";
    }
  }
  delete a;
}
'
bash-3.2$  match1.xml.awk
a:a[0]=<a><c>kjkjkj</c></a><b>jkjk</b><a>jkjk</a><d>dddd</d> RSTART=1 RLENGTH=53
a:i=1 a[1]=</d> |
a:i=2 a[2]=/d |
a:i=3 a[3]= |
a:a[0]= RSTART=1 RLENGTH=0
b:i=1 a[1]= |
b:i=2 a[2]= |
b:i=3 a[3]= |
a:a[0]=aaaaaaaaa44444bbbbbbbb7777777ccccccc99999dddddddd000000 RSTART=1 RLENGTH=55
b:i=1 a[1]=dddddddd000000 |
b:i=2 a[2]=dddddddd |
b:i=3 a[3]=000000 |

a[0]是匹配全文,a[1]是最后一遍第1个(),是最外层的,a[2]是第2个(),也是内层前1个,a[3]是第3个(),也是内层后1个。
重复匹配时,只有最后一遍记住了。

[ 本帖最后由 zhangshebao 于 2009-1-20 21:34 编辑 ]

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
2 [报告]
发表于 2009-01-20 08:43 |只看该作者
1.正则表达式是贪婪的
2.*可以匹配0个
3.你只用了三个()捕捉,可以得到6个结果?

论坛徽章:
0
3 [报告]
发表于 2009-01-20 21:37 |只看该作者
谢谢waker.
match(s,r,a)贴子不多,希望对大家有用。
如果有办法让awk记住重复匹配的()就更好了。

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
4 [报告]
发表于 2009-01-21 09:54 |只看该作者
其实有个落后而广泛应用的方法,match与sub联用
http://phi.sinica.edu.tw/aspac/reports/94/94011/append_c.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP