Perl-расщепление и регулярное выражение - PullRequest
0 голосов
/ 13 января 2019

У меня есть строка текста, такая как

Это "тест" для очень интересных "проблем", которые можно "решить"

И я пытаюсь разделить его так, чтобы мой массив @goodtext содержал столько строк из цитируемых разделов. Так что мой массив будет содержать следующее:

$goodtext[0] is
$goodtext[1] of very interesting
$goodtext[2] that can

Количество цитируемых разделов в каждой строке варьируется, к сожалению ...

Ответы [ 3 ]

0 голосов
/ 13 января 2019

Предполагается, что не может быть разумного вложения

my @quoted = $string =~ /"([^"]+)"/g;

или, если вам нужно уметь обрабатывать их, собирая их

my @quoted;    
while ($string =~ /"([^"]+)"/g) {      #" (stop faulty markup highlight)
    # ...
    push @quoted, $1;
}

Обратите внимание, что нам нужно закрытие ", хотя [^"]+ будет соответствовать ему в любом случае. Это сделано для того, чтобы двигатель его потреблял и проходил мимо, поэтому следующее совпадение " действительно является следующим открытием.

Если кавычки " также могут быть" вложены "", тогда вы захотите Text::Balanced


Кроме того, обратите внимание на различие в поведении модификатора /g в списке и скалярных контекстах .

  • В контексте списка, навязанном списком (в первом примере - @quoted), с модификатором /g оператор match возвращает список всех захватов, или всех совпадений, если в шаблоне нет захвата (без паренов)

  • В скалярном контексте, когда оценивается как условие while (например), его поведение с /g является более сложным. После сопоставления в следующий раз, когда регулярное выражение запускается, оно продолжает поиск строки с позиции (один после) предыдущего совпадения, перебирая совпадения.

    Обратите внимание, что нам не нужен цикл для этого (что является тонкой причиной для тонких ошибок)

    my $string = q(one simple string);
    
    $string =~ /(\w+)/g; 
    say $1;               #--> one
    
    $string =~ /(\w+)g;
    say $1;               #--> simple
    

    Без /g ни в одном из регулярных выражений мы не получаем такого поведения, скорее, one печатается оба раза.

См. Глобальное соответствие в perlretut , и, например, \G утверждение в perlop и pos

0 голосов
/ 13 февраля 2019

Попробуйте это.

$ a='This "is" a test "of very interesting" problems "that can" be solved'

$ echo $a | perl -lne ' @arr=$_=~/"(.+?)"/g; print join("\n",@arr) '
is
of very interesting
that can

$
0 голосов
/ 13 января 2019

Пример использования Text :: Balanced для извлечения цитируемых подстрок:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw/say/;
use Text::Balanced qw/extract_multiple extract_delimited/;

my $test = q{This "is" a test "of very interesting" problems "that can" be solved};

sub just_quotes {
  extract_multiple $_[0], [ sub { extract_delimited $_[0], '"' } ], undef, 1;
}

say for just_quotes $test;

это даст:

"is"
"of very interesting"
"that can"
...