免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1015 | 回复: 7

[文本处理] 寻找文本段中与某行“{”和“}”进行匹配的行 [复制链接]

论坛徽章:
0
发表于 2016-09-24 18:23 |显示全部楼层
本帖最后由 junhengwoo 于 2016-09-24 18:43 编辑

现在有一段文本,需要在其中查找与某行号下面“{”和“}”进行匹配的行号。
假设行号A是要开始行号,行号B是结束行号。当然,行号B大于或等于行号A。
查找的规则如下:
1) 行号B所在的行中有“}”;
2) 行号A到行号B之间的文本段(包括行号A和行号B所在的行)中,“{”和“}”出现的次数相等,这个次数大于0;
3) 文本段中,“{”和“}”是配对可以嵌套出现的;
4) 行号B是满足上面的规则1和规则2的第一个行号;

示例一,开始行号是2,那么要查找到的行号也是2。
1. aaa
2. a{b}c


示例二,开始行号是2,那么要查找到的行号是4。
1. aaa
2. a{bc
3. ddd
4. eee{}}
5. ccc{}

示例三,开始行号是1,那么要查找到的行号是6。
1. aaa
2. a{bc
3. ddd
4. eee{}
5. ccc{}
6. ddd}
7. ff


请各位大神帮忙看看,如何用awk或sed来实现。






论坛徽章:
28
15-16赛季CBA联赛之八一
日期:2016-02-22 19:10:4215-16赛季CBA联赛之深圳
日期:2016-12-01 10:34:0415-16赛季CBA联赛之新疆
日期:2016-12-07 10:24:2915-16赛季CBA联赛之同曦
日期:2016-12-15 12:06:43CU十四周年纪念徽章
日期:2016-12-18 13:03:4415-16赛季CBA联赛之吉林
日期:2017-01-03 15:52:2515-16赛季CBA联赛之辽宁
日期:2017-01-04 14:58:2415-16赛季CBA联赛之辽宁
日期:2017-01-15 09:42:512016科比退役纪念章
日期:2017-02-06 17:21:50黑曼巴
日期:2017-02-10 15:46:1215-16赛季CBA联赛之上海
日期:2017-03-18 10:14:5415-16赛季CBA联赛之青岛
日期:2017-03-18 22:00:44
发表于 2016-09-24 20:36 |显示全部楼层
本帖最后由 moperyblue 于 2016-09-26 11:41 编辑

echo '1. aaa
2. a{bc
3. ddd
4. eee{}
5. ccc{}
6. ddd}
7. ff'|awk -v nr=1 'NR>=nr&&!f{if(/{/)f=1}f{if(/{/)i+=gsub(/{/,"&");if(/}/)i-=gsub(/}/,"&");if(i==0){print "B=>"NR;exit}}'

论坛徽章:
2
luobin
日期:2016-06-17 17:46:36lufei
日期:2016-06-17 17:49:16
发表于 2016-09-24 22:15 |显示全部楼层
  1. awk 'BEGIN{a=0;b=0}/\{/{a+=gsub(/{/,"&");if(a==1)print "first line: " NR}{b+=gsub(/}/,"&");if(a==b && a!=0)exit}END{print "second line: "NR;}' file2
复制代码

论坛徽章:
20
卯兔
日期:2015-01-26 22:05:142015亚冠之萨济拖拉机
日期:2015-09-10 15:15:282015亚冠之阿尔希拉尔
日期:2015-09-25 17:37:53程序设计版块每日发帖之星
日期:2015-10-03 06:20:00程序设计版块每日发帖之星
日期:2015-12-09 06:20:00CU十四周年纪念徽章
日期:2015-12-17 09:07:15程序设计版块每日发帖之星
日期:2015-12-25 06:20:34程序设计版块每日发帖之星
日期:2015-12-25 06:20:34程序设计版块每日发帖之星
日期:2015-12-25 06:20:342015亚冠之广州富力
日期:2015-08-27 19:29:56每日论坛发贴之星
日期:2015-08-26 06:20:002015亚冠之阿尔希拉尔
日期:2015-05-18 17:26:27
发表于 2016-09-26 00:41 |显示全部楼层
回复 1# junhengwoo
  1. sed -n ':1;s#{##;t2;:3;s#}##;t4;T;:2;x;s#^#.#;x;t1;:4;x;s#.##;/^$/{=;q};x;t3' file
复制代码

论坛徽章:
28
15-16赛季CBA联赛之八一
日期:2016-02-22 19:10:4215-16赛季CBA联赛之深圳
日期:2016-12-01 10:34:0415-16赛季CBA联赛之新疆
日期:2016-12-07 10:24:2915-16赛季CBA联赛之同曦
日期:2016-12-15 12:06:43CU十四周年纪念徽章
日期:2016-12-18 13:03:4415-16赛季CBA联赛之吉林
日期:2017-01-03 15:52:2515-16赛季CBA联赛之辽宁
日期:2017-01-04 14:58:2415-16赛季CBA联赛之辽宁
日期:2017-01-15 09:42:512016科比退役纪念章
日期:2017-02-06 17:21:50黑曼巴
日期:2017-02-10 15:46:1215-16赛季CBA联赛之上海
日期:2017-03-18 10:14:5415-16赛季CBA联赛之青岛
日期:2017-03-18 22:00:44
发表于 2016-09-26 08:42 |显示全部楼层
本帖最后由 moperyblue 于 2016-09-26 08:48 编辑

#示例一,开始行号是2,那么要查找到的行号也是2。
sed -n '2{:a;/{/{s///;x;s/^/./;x;ta};/}/{s///;x;s/.//;/./!{=;q};x;ta};n;ba}'

#示例二,开始行号是2,那么要查找到的行号是4。
sed -n '2{:a;/{/{s///;x;s/^/./;x;ta};/}/{s///;x;s/.//;/./!{=;q};x;ta};n;ba}'

#示例三,开始行号是1,那么要查找到的行号是6。
sed -n '1{:a;/{/{s///;x;s/^/./;x;ta};/}/{s///;x;s/.//;/./!{=;q};x;ta};n;ba}'

论坛徽章:
0
发表于 2016-09-26 10:55 |显示全部楼层
回复 2# moperyblue

测试结果符合预期,谢谢大神。请问awk中的f是什么啊? 没看明白

论坛徽章:
0
发表于 2016-09-26 11:17 |显示全部楼层
回复 3# hz_oracle

这个也可行。但我需要把起始行号作为变量传到awk里,请帮忙看看要怎么处理啊

论坛徽章:
28
15-16赛季CBA联赛之八一
日期:2016-02-22 19:10:4215-16赛季CBA联赛之深圳
日期:2016-12-01 10:34:0415-16赛季CBA联赛之新疆
日期:2016-12-07 10:24:2915-16赛季CBA联赛之同曦
日期:2016-12-15 12:06:43CU十四周年纪念徽章
日期:2016-12-18 13:03:4415-16赛季CBA联赛之吉林
日期:2017-01-03 15:52:2515-16赛季CBA联赛之辽宁
日期:2017-01-04 14:58:2415-16赛季CBA联赛之辽宁
日期:2017-01-15 09:42:512016科比退役纪念章
日期:2017-02-06 17:21:50黑曼巴
日期:2017-02-10 15:46:1215-16赛季CBA联赛之上海
日期:2017-03-18 10:14:5415-16赛季CBA联赛之青岛
日期:2017-03-18 22:00:44
发表于 2016-09-26 11:43 |显示全部楼层
回复 6# junhengwoo

一个用于标识的普通变量
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP