Perl的 - 正则表达式只提取逗号分隔的字符串

问题描述:

我有一个问题,我希望有人能够帮助有...Perl的 - 正则表达式只提取逗号分隔的字符串

我有一个包含从网页内容的变量(使用WWW刮::机械化)。

的变量包含如这些数据:

$var = "ewrfs sdfdsf cat_dog,horse,rabbit,chicken-pig" 
$var = "fdsf iiukui aawwe dffg elephant,MOUSE_RAT,spider,lion-tiger hdsfds jdlkf sdf" 
$var = "dsadp poids pewqwe ANTELOPE-GIRAFFE,frOG,fish,crab,kangaROO-KOALA sdfdsf hkew" 

唯一位我对从上述实施例是:

@array = ("cat_dog","horse","rabbit","chicken-pig") 
@array = ("elephant","MOUSE_RAT","spider","lion-tiger") 
@array = ("ANTELOPE-GIRAFFE","frOG","fish","crab","kangaROO-KOALA") 

我遇到的问题:

我想从变量中只提取逗号分隔的字符串,然后将这些字符串存储在数组*以后使用。

但是最好的方法是确保我得到的字符串在开始(即cat_dog)和结束(即鸡 - 猪)的逗号分隔的动物列表,因为它们没有前缀/后缀逗号。

此外,因为变量将包含相关的网页内容,这是必然的,有可能的情况,其中一个逗号是立即被一个空格,然后另一个词成功,因为这是使用逗号的正确方法在段落和句子......

例如:

Saturn was long thought to be the only ringed planet, however, this is now known not to be the case. 
                ^ ^
                |  | 
            note the spaces here and here 

我没有兴趣在逗号后面有一个空格(如上图所示),任何情况下。

我只在逗号没有后(即cat_dog,马,兔,鸡,猪)的空间的情况下有意

我有一个尝试了一些这样做的方法,但无法找出构建正则表达式的最佳方式。

+1

如果你添加你遇到麻烦... – pavel 2013-04-25 11:30:48

如何

[^,\s]+(,[^,\s]+)+ 

这将匹配一个或多个字符不是一个空格或逗号[^,\s]+后跟一个逗号和一个或多个字符不是一个空格或逗号,一次或多次。

继评论

要匹配多个序列添加g修饰符全局匹配。
下面将,上的每个匹配$&分开,并将结果推送到@matches

my $str = "sdfds cat_dog,horse,rabbit,chicken-pig then some more pig,duck,goose"; 
my @matches; 

while ($str =~ /[^,\s]+(,[^,\s]+)+/g) { 
    push(@matches, split(/,/, $&)); 
} 

print join("\n",@matches),"\n"; 
+0

的代码,那么什么是推动这些方式的正确方法这将有助于阵列?因为使用'foreach'($ var1 =〜/ [^,\ s] +(,[^,\ s])来使用变量,如sdfds cat_dog,马,兔子,鸡 - 猪以及更多的猪,鸭,鹅' +){/ 0} { push(@personal,$ _);'只将第一个匹配的'cat_dog,horse,rabbit,chicken-pig'添加到数组中,并且不添加'pig,duck,goose'?感谢您的帮助 – 2013-04-25 14:16:21

+0

@ perl-user。进一步查询后更新答案。 – MikeM 2013-04-25 15:20:27

+0

非常感谢,感谢您的帮助 – 2013-04-25 15:26:24

$var =~ tr/ //s;  
while ($var =~ /(?<!,)\b[^, ]+(?=,\S)|(?<=,)[^, ]+(?=,)|(?<=\S,)[^, ]+\b(?! ,)/g) { 
     push (@arr, $&); 
    } 

正则表达式3案件匹配:

(?<!,)\b[^, ]+(?=,\S) : matches cat_dog 
(?<=,)[^, ]+(?=,)  : matches horse & rabbit 
(?<=\S,)[^, ]+\b(?! ,) : matches chicken-pig 
+1

这个错误地匹配了他正常标点符号的例子。编辑为 – TLP 2013-04-25 11:39:23

+0

以与正常标点符号不匹配 – 2013-04-25 12:34:02

虽然你也许可以建立一个单一的正则表达式,regexs,split S,grepmap的组合看起来体面

my @array = map { split /,/ } grep { !/^,/ && !/,$/ && /,/ } split 

从右到左:

  1. 拆分上空间中的线(split
  2. 只留下不具有逗号在任一端,但具有一个内部(grep
  3. 拆分每一个这样的元件成零件(mapsplit)元素

这样你可以很容易地改变零件eg在grep内部添加&& !/,,/以消除连续的两个逗号。

我希望这是明确的,适合您的需要:

#!/usr/bin/perl 
    use warnings; 
    use strict; 

    my @strs = ("ewrfs sdfdsf cat_dog,horse,rabbit,chicken-pig", 
    "fdsf iiukui aawwe dffg elephant,MOUSE_RAT,spider,lion-tiger hdsfds jdlkf sdf", 
    "dsadp poids pewqwe ANTELOPE-GIRAFFE,frOG,fish,crab,kangaROO-KOALA sdfdsf hkew", 
    "Saturn was long thought to be the only ringed planet, however, this is now known not to be the case.", 
    "Another sentence, although having commas, should not confuse the regex with this: a,b,c,d"); 

    my $regex = qr/ 
       \s #From your examples, it seems as if every 
        #comma separated list is preceded by a space. 
       (
        (?: 
         [^,\s]+ #Now, not a comma or a space for the 
           #terms of the list 

         ,  #followed by a comma 
        )+ 
        [^,\s]+  #followed by one last term of the list 
       ) 
       /x; 

    my @matches = map { 
        $_ =~ /$regex/; 
        if ($1) { 
         my $comma_sep_list = $1; 
         [split ',', $comma_sep_list]; 
        } 
        else { 
         [] 
        } 
       } @strs;