2013-04-25 3 views
4

У меня есть вопрос, который я надеюсь кто-то может помочь с ...Perl - Regex для извлечения только через запятую струне

У меня есть переменная, которая содержит контент с веб-страницы (соскабливают с помощью WWW :: Mechanize).

Переменная содержит такие данные, как эти:

$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" 

The только бит я заинтересован из приведенных выше примеров являются:

@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

ответ

8

Как насчет

[^,\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

Что бы тогда быть правильный метод, чтобы подтолкнуть их к массив? Потому что, используя переменную, такую ​​как 'sdfds cat_dog, лошадь, кролик, курица-свинья, а затем еще несколько свиней, уток, гусь', используя' foreach ($ var1 = ~/[^, \ s] + (, [^, \ s] +) + /) { push (@personal, $ _); 'добавляет в массив первое совпадение' cat_dog, лошадь, кролик, курица-свиньи' и не добавляет 'свиньи, утки, гуся'? Спасибо за вашу помощь –

+0

@ perl-user. Обновленный ответ на дальнейший запрос. – MikeM

+0

Отличное спасибо, оцените вашу помощь –

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

регулярное выражение соответствует три случая:

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

Это ложное совпадение с его примером нормальной пунктуации. – TLP

+0

отредактирован, чтобы не соответствовать нормальной пунктуации –

1

Хотя вы, вероятно, можете построить один регулярное выражение, сочетание regexs, split с, grep и map выглядит прилично

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

Переход справа налево:

  1. Сплит линия на пространствах (split)
  2. Оставьте только элементы, не имеющие запятой на обоих концах, но имеющие одну внутреннюю (grep)
  3. Split каждый такой элемент на части (map и split)

Таким образом, вы можете легко изменить детали, например для устранения двух последовательных запятых добавить && !/,,/ внутри grep.

1

Я надеюсь, что это понятно и соответствует вашим потребностям:

#!/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;