регулярное выражение s / ^ (. *?): \ s * // - PullRequest
0 голосов
/ 29 декабря 2011

В следующем примере Perl используется регулярное выражение, т.е. next unless s/^(.*?):\s*//; Но, как понять это регулярное выражение, s/^(.*?):\s*//

while ( <> ) {
next unless s/^(.*?):\s*//;
$HoA{$1} = [ split ];
}

Ответы [ 3 ]

4 голосов
/ 29 декабря 2011

Он захватывает (и сохраняет как $1) некоторый текст до :.Затем он удаляет захваченный текст, точку с запятой и любые пробелы в конце.

За пределами регулярного выражения: если регулярному выражению удалось выполнить свою работу, то код использует захваченный текст в качестве ключа хеша, значение которого является ссылкой на массив.Элементами этого массива являются оставшаяся часть строки, разделенная пробелами.

#!/usr/bin/env perl

use strict;
use warnings;

use Data::Dumper;

my %HoA;

while ( <DATA> ) {
  #next unless s/^(.*?):\s*//;
  next unless 
    s/      #s is replace match operation
      ^     #start at the beginning of the line
      (     #begin capture $1
        .*? #capture anything, but not greedy, i.e. stop before :
      )     #end capture $1
      :     #literal colon (must match)
      \s*   #optional whitespace
    //x;    #replace match with nothing, x flag allows formatting and comments
  $HoA{$1} = [ split ];
}

print Dumper(\%HoA), "\n";

__DATA__

Thingy: Thing1 Thing2
Stuff: mystuff yourstuff
other line that doesn't have a colon

дает

$VAR1 = {
          'Thingy' => [
                        'Thing1',
                        'Thing2'
                      ],
          'Stuff' => [
                       'mystuff',
                       'yourstuff'
                     ]
        };
1 голос
/ 29 декабря 2011

Он совпадает с начала строки (^) до :, захватывая все, что находится между ((.*?)), и любые последующие пробелы (\s*), и заменяет его (s/regex/replacement/) на пустая строка.

Возвращает истинное значение (количество выполненных замен), если оно совпадает, в противном случае - ложное.

Например, когда $_ равно foo: bar, оно будет соответствовать foo: и заменено, в результате $_ будет bar. После чего первая группа захвата $1 будет содержать foo.

Чтобы узнать больше, взгляните на:

0 голосов
/ 29 декабря 2011

Они используют много старых ярлыков, которые больше не используют большинство людей. Вот код снова с отсутствующей переменной по умолчанию. Я также перевернул оператор unless в более стандартный формат. То есть я сделал это оператором if и поместил next как часть блока if:

while ( $_ = <> ) {
    if (not $_ =~ s/^(.*?):\s*//) {
       next;
    }
    $HoA{$1} = [ split(/\s+/, $_) ];
}

Итак, мы устанавливаем значение $_ из оператора diamond . Это в основном берет имена файлов в командной строке и читает каждую строку в этих файлах. Если в командной строке нет файлов, она считывает из STDIN.

Регулярное выражение сложнее. ^ привязывает регулярное выражение к началу строки. В противном случае регулярное выражение может появиться в любом месте строки. Например:

/FOO/    #Will match "FOOBAR"  "BARFOOBAR", or "BARFOO"
/^FOO/   #Will only match "FOOBAR" and not "BARFOOBAR" or "BARFOO"

. означает любой символ. * означает ноль или более из предыдущего. Таким образом, .* означает любое количество символов (включая ноль символов. Например:

/^.*:/   #Will match any combination of characters followed by a colon (:).

Таким образом, это будет соответствовать : на отдельной строке (ноль или более) или this is a test:

Хитрая часть - это ?, которая очень тонко меняет значение *. Обычно регулярные выражения являются жадными. Они пытаются найти наиболее подходящее совпадение, поэтому если у вас есть строка:

my $string = "abc:def:ghij";
$string =~ /^.*:/;

Регулярное выражение будет соответствовать как можно большему. Таким образом, приведенное выше будет соответствовать abc:def:, поскольку это самая длинная строка, которая заканчивается двоеточием. Помещая ? после *, вы делаете регулярное выражение как non-жадный - то есть оно будет соответствовать наименьшему возможному выражению. Таким образом:

my $string = "abc:def:ghij";
$string =~ /^(.*):/   #Matches "abc:def:
$string =~ /^(.*?):/  #Matches "abc:"

\s означает любой пробел, который обычно означает пробел или символ табуляции. * означает ноль или более этих пробелов. Таким образом, это не может быть ни пробел, ни несколько пробелов.

my $string = "abc:def:  foo";
$string =~ /^(.*?):\s*/;   #Matches "abc:"
$string = "abc:   This is a test";
$string =~ /^(.*?):\s*/;   #Matches "abc:   "

Теперь s перед регулярным выражением означает замену. Базовый формат:

$string =~ s/regex/string/;

Где regex - это регулярное выражение, соответствующее чему-то в $string, а string - замена для совпадения. Простой пример:

$string = "My name is David";
$string =~ s/David/Bill/;    #String is now "My name is Bill"

В этом случае символы, соответствующие регулярному выражению, просто заменяются ничем. То есть они удаляются из строки:

$string = "abc:  def";
$string =~ /^(.*?):\s*/;   #$string is now "def". "abc:   " has been removed

Итак, еще один взгляд на ваш код:

while ( $_ = <> ) {
    if (not $_ =~ s/^(.*?):\s*//) {
       next;
    }
    $HoA{$1} = [ split(/\s+/, $_) ];
}

Это чтение из файлов, перечисленных в командной строке, или из STDIN, и ищет строки, содержащие двоеточие. Если строка не содержит двоеточия, она читает следующую строку.

Если строка содержит двоеточие, первая часть строки до first двоеточия и все последующие пробелы удаляются из строки.

$1 относится к той части строки, которая была найдена в скобках в предыдущем регулярном выражении. Это первая часть строки до первого двоеточия. split разделяет оставшуюся часть строки, разделенную пробелами, и превращает ее в так называемый анонимный список . То есть, это создает хэш массивов (именно поэтому этот хэш называется HoA (Хэш массивов).

Давайте приведем несколько примеров строк:

____________________________________________________
|     STRING      |           RESULTS              |
|_________________|________________________________|
| abc:  foobar    | $HoA{abc} = ["foobar"]         |
| def:bar fu      | $HoA{def} = ["bar", "fu"]      |
| ghi:jkl:mno     | $HoA{ghi} = ["jkl:mno"]        |
| ghi :  jkl: mn: | $HoA{"ghi "} = ["jkl:", "mn:"] |
|_________________|________________________________|

Обратите внимание, что у последнего будет пробел в конце ключа. Это "Гхи", а не "Гхи".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...