免费注册 查看新帖 |

Chinaunix

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

求助Perl 正则循环匹配问题. [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-07-10 11:01 |只看该作者 |倒序浏览
本帖最后由 watergun 于 2015-07-10 11:26 编辑

请教各位一个问题啊. 我有一个字符串. 需要split成字符数组.
例子:  例子中的A,B,C是任何可能长度的字符,或者数字.

$line=qq{A,A,B,C};
以前直接用
  1. @result = split ("," $line);
复制代码
来处理.
得到:
A
A
B
C

后来发现有这种情况:
$line=qq{A,"A,A",B,C};
需要把A,A当作一个来处理. 我就google了一个代码. 一直使用. 没问题.
  1. push(@fields, $+) while $line =~ m{
  2.       "([^\"\\]*(?:\\.[^\"\\]*)*)",?  # groups the phrase inside the quotes
  3.       | ([^,]+),?
  4.       | ,
  5.       }gx;
复制代码
得到
A
"A,A"
B
C

昨天发现情况更复杂了...
$line=qq{A,"A,"A,A"",B,C};
出现了一个"A,"A,A"" 需要匹配成单独的字符串.. 也就是双引号嵌套了. 而且嵌套里面还有逗号..
我不知道该怎么做这个split了..
想得到的结果是:
A
"A,"A,A""
B
C
应该对应以"开头, 以",或者"$为结束的为一个字符串. 其他都以,分割.
我对正则不是很擅长,麻烦有没有高手帮忙.
谢谢了...

论坛徽章:
0
2 [报告]
发表于 2015-07-10 14:28 |只看该作者
有没有人帮忙啊... 谢谢了啊...

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
3 [报告]
发表于 2015-07-10 16:34 |只看该作者
回复 1# watergun


    你这双引号一嵌套,外面的双引号和里面的要怎么区分?

论坛徽章:
0
4 [报告]
发表于 2015-07-10 16:43 |只看该作者
本帖最后由 watergun 于 2015-07-10 16:46 编辑

只有一中方法能区分
外面的双引号是以 ", 或者 "$ 为结尾的. 里面的不是.

整了快一天了.. 写不出来啊.
用 (\"([^\"]|[\"[^,]).*?)\",)  能匹配到第二和第三种的内容. 但是具体怎么做循环.. 还是一头雾水.

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
5 [报告]
发表于 2015-07-10 17:11 |只看该作者
回复 4# watergun


    这个用正则做已经比较困难了,因为在扫描到 " 的时候要记录一些状态,你可以用 Parse::Lex 写个简单的 lexer,或者自己手写个也行:

  1. #!/usr/bin/perl

  2. use strict;
  3. use warnings;

  4. use v5.12;
  5. use Data::Dumper;

  6. my $data = qq{sss1, 123, "sss2", "sss3,sss4", "sss5,"sss6,sss7"", sss8, "sss9"};

  7. my ($level, @token_buf, @token);

  8. $level = 0;
  9. my @chars = split //, $data;

  10. while (my ($i, $c) = each @chars) {
  11.     given ($c) {
  12.         when (/,/) {
  13.             if ($level > 0) {
  14.                 push @token_buf, $c;
  15.             } else {
  16.                 push @token, (join '', @token_buf);
  17.                 @token_buf = ();
  18.             }
  19.         }
  20.         when (/"/) {
  21.             my $nc = $chars[$i+1];
  22.             if ($nc eq '"' or $nc eq ',' or !defined $nc) {
  23.                 $level--;
  24.                 push @token_buf, $c if $level > 0;
  25.             } else {
  26.                 push @token_buf, $c if $level > 0;
  27.                 $level++;
  28.             }
  29.         }
  30.         when (/ /) { }
  31.         default { push @token_buf, $c; }
  32.     }
  33. }
  34. push @token, (join '', @token_buf);

  35. say "Data: $data";
  36. say Dumper(\@token);
复制代码

论坛徽章:
26
2015亚冠之胡齐斯坦钢铁
日期:2015-06-25 21:40:202015亚冠之柏斯波利斯
日期:2015-08-31 17:03:192015亚冠之柏斯波利斯
日期:2015-11-07 13:10:00程序设计版块每日发帖之星
日期:2015-11-10 06:20:00每日论坛发贴之星
日期:2015-11-10 06:20:00程序设计版块每日发帖之星
日期:2015-11-26 06:20:00程序设计版块每日发帖之星
日期:2015-12-02 06:20:00黄金圣斗士
日期:2015-12-07 17:57:4615-16赛季CBA联赛之天津
日期:2015-12-23 18:34:14程序设计版块每日发帖之星
日期:2016-01-02 06:20:00程序设计版块每日发帖之星
日期:2016-01-06 06:20:00每日论坛发贴之星
日期:2016-01-06 06:20:00
6 [报告]
发表于 2015-07-10 17:27 |只看该作者
对正则不擅长
我这么写了
___________________
A,A,B,C
___________________
A
A
B
C
___________________
A,"A,A",B,C
___________________
A
"A,A"
B
C
___________________
A,"A,"A,A"",B,C
___________________
A
"A,"A,A""
B
C
___________________
A,""A",A",B,C
___________________
A
""A",A"
B
C
  1. #!/usr/bin/perl
  2. use 5.010;

  3. while (<DATA>) {
  4.     my $line   = $_;
  5.     my @result = SPLIT($line);
  6.     say '___________________';
  7.     print $_;
  8.     say '___________________';
  9.     say for @result;
  10. }

  11. sub SPLIT {
  12.     my $LINE   = shift;
  13.     my $APPEND = 0;
  14.     my @FIELDS;

  15.     for ( split /,|\n/, $LINE ) {
  16.         $APPEND ? $FIELDS[-1] .= ",$_" : push @FIELDS, $_;
  17.         my ( $PREFIX, $SUFIX ) = /^("*)\w+("*)$/;
  18.         $APPEND += $PREFIX =~ tr/"// if $PREFIX;
  19.         $APPEND -= $SUFIX =~ tr/"// if $SUFIX;
  20.     }
  21.     return @FIELDS;
  22. }


  23. __DATA__
  24. A,A,B,C
  25. A,"A,A",B,C
  26. A,"A,"A,A"",B,C
  27. A,""A",A",B,C
复制代码

论坛徽章:
0
7 [报告]
发表于 2015-07-10 18:02 |只看该作者
本帖最后由 watergun 于 2015-07-10 18:12 编辑

回复 5# MMMIX

非常非常感谢. 但是我在试着运行的时候遇到下面的错误.

Type of arg 1 to each must be hash (not private array) at ./double_quotes_test.pl line 13, near "@chars) "

应该是这行

while (my ($i, $c) = each @chars) {

这是为什么.. each应该用在哈希上吧. 能这样用在数组吗? 我不太理解.
   

论坛徽章:
0
8 [报告]
发表于 2015-07-10 18:05 |只看该作者
本帖最后由 watergun 于 2015-07-10 18:06 编辑

回复 6# substr函数

非常非常感谢. 我给的例子运行的都没问题. 但是不知道怎么回事. 在实际运行的时候就失败了..  实际的例子是:

IT-VME,IT-VME-VMWARE9,nonreplicated,BACKUP,"-vmfulltype=vstor -vmbackuptype=fullvm -asnodename=MITC  -domain.vmfull="VMHOST=vmware9.it-servers.louisville.edu;-VM=Tegrity-Prod,*-NB,tsmpbw*,sp2010sql*,Print*,test-clus-sp*" -MODE=IFIncremental",,5,2013-07-08,22:09:00,4,HOURS,,,"Sun,Mon,Tue,Wed,Thu,Fri,Sat",,2014-06-11 15:40:12.000000,SYSDEE,


结果是:

___________________
  1. IT-VME,IT-VME-VMWARE9,nonreplicated,BACKUP,"-vmfulltype=vstor -vmbackuptype=fullvm -asnodename=MITC -domain.vmfull="VMHOST=vmware9.it-servers.louisville.edu;-VM=Tegrity-Prod,*-NB,tsmpbw*,sp2010sql*,Print*,test-clus-sp*" -MODE=IFIncremental",,5,2013-07-08,22:09:00,4,HOURS,,,"Sun,Mon,Tue,Wed,Thu,Fri,Sat",,2014-06-11 15:40:12.000000,SYSDEE,
  2. ___________________
  3. $VAR1 = 'IT-VME';
  4. $VAR2 = 'IT-VME-VMWARE9';
  5. $VAR3 = 'nonreplicated';
  6. $VAR4 = 'BACKUP';
  7. $VAR5 = '"-vmfulltype=vstor -vmbackuptype=fullvm -asnodename=MITC -domain.vmfull="VMHOST=vmware9.it-servers.louisville.edu;-VM=Tegrity-Prod';
  8. $VAR6 = '*-NB';
  9. $VAR7 = 'tsmpbw*';
  10. $VAR8 = 'sp2010sql*';
  11. $VAR9 = 'Print*';
  12. $VAR10 = 'test-clus-sp*" -MODE=IFIncremental"';
  13. $VAR11 = '';
  14. $VAR12 = '5';
  15. $VAR13 = '2013-07-08';
  16. $VAR14 = '22:09:00';
  17. $VAR15 = '4';
  18. $VAR16 = 'HOURS';
  19. $VAR17 = '';
  20. $VAR18 = '';
  21. $VAR19 = '"Sun,Mon,Tue,Wed,Thu,Fri,Sat"';
  22. $VAR20 = '';
  23. $VAR21 = '2014-06-11 15:40:12.000000';
  24. $VAR22 = 'SYSDEE';
复制代码
在 Tegrity-Prod 这里被截断了. 不应该截断的. 我先去搞明白你的代码吧.. 太谢谢了.
   

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
9 [报告]
发表于 2015-07-10 18:18 |只看该作者
watergun 发表于 2015-07-10 18:02
回复 5# MMMIX
each应该用在哈希上吧. 能这样用在数组吗?


这是 5.12 的新特性。

论坛徽章:
0
10 [报告]
发表于 2015-07-10 18:31 |只看该作者
回复 9# MMMIX

为什么我的环境就不行呢?
  1. [sguser@sg-rhel5-12 bin]$ sg-perl -v

  2. This is perl, v5.8.1 built for i686-linux
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP