Perl соответствует только возвращающему «1». Булевы? Зачем? - PullRequest
6 голосов
/ 22 октября 2011

Это должно быть очевидно, но я просто не вижу этого.

У меня есть документы, содержащие тысячи записей, как показано ниже:

Row:1 DATA:
[0]37755442
[1]DDG00000010
[2]FALLS
[3]IMAGE
[4]Defect
[5]3
[6]CLOSED

Мне удалосьотделить каждую запись, и теперь я пытаюсь разобрать каждое поле.

Я пытаюсь сопоставить пронумерованные заголовки, чтобы я мог извлечь данные, которые следуют за ними, но проблема в том, что мои совпадениятолько возвращая мне «1», когда им это удается, и ничего, если они этого не делают.Это происходит для любого совпадения, которое я пытаюсь применить.

Например, применяется к простому слову в каждой записи:

my($foo) = $record=~ /Defect/;
print STDOUT $foo;

выводит «1» для каждой записи, если оносодержит «Дефект» и ничего, если он содержит что-то еще.

В качестве альтернативы:

$record =~ /Defect/;
print STDOUT $1;

абсолютно ничего не печатает.

$record =~ s/Defect/Blefect/

заменит «Дефект» на «Blefect»"отлично, с другой стороны.

Я действительно смущен тем, почему отдача от моих спичек такая странная.Любая помощь будет высоко ценится.

Ответы [ 6 ]

17 голосов
/ 22 октября 2011

Вы должны использовать захватные скобки для фактического захвата:

if ($record =~ /(Defect)/ ) {
    print "$1\n";
}
7 голосов
/ 22 октября 2011

Я думаю, что вы действительно хотите заключить регулярное выражение в скобки:

my($foo) = $record=~ /(Defect)/;

В контексте списка возвращаются группы, а не само совпадение. А в вашем исходном коде нет групп.

4 голосов
/ 22 октября 2011

Оператор Perl =~ принимает строку (левый операнд) и регулярное выражение (правый операнд) и сопоставляет строку с RE, возвращая логическое значение (true или false) в зависимости от того, совпадает ли re.

Теперь Perl на самом деле не имеет логического типа - вместо этого каждое значение (любого типа) обрабатывается как «истина» или «ложь» в логическом контексте - большинство вещей «истинно», нопустая строка и специальное значение undef для неопределенных вещей - false.Поэтому, возвращая логическое значение, он обычно использует «1» для true и «» (пустая строка) для false.

Теперь, что касается вашего последнего вопроса, где при попытке напечатать $1 ничего не печатается.Всякий раз, когда вы сопоставляете регулярное выражение, perl устанавливает $1, $2 ... в значения вложенных выражений в скобках с RE.Однако в вашем примере нет выражений, заключенных в скобки, поэтому $ 1 всегда пусто.Если вы измените его на

$record =~ /(Defect)/;
print STDOUT $1;

, вы получите нечто большее, чем вы ожидаете (Defect, если оно совпадает, и ничего, если не соответствует).

Наиболее распространенная идиомадля соответствия регулярному выражению я обычно вижу что-то вроде:

if ($string =~ /regexp with () subexpressions/) {
    ... code that uses $1 etc for the subexpressions matched
} else {
    ... code for when the expression doesn't match at all
}
2 голосов
/ 22 октября 2011

С операторы perlop, Quote и Quote-Like [биты в скобках, добавленные мной]:

/ PATTERN / msixpodualgc

Поиск строки длясовпадение с шаблоном, и в скалярном контексте возвращает true [1], если он успешен, false [undef], если он терпит неудачу.

(Просмотр раздела на s/// приведет ктакже полезно; -)

Perl просто не имеет дискретного логического типа или true / false псевдонимов, поэтому часто используются 1 и undef: однако, это вполне может быть может быть другими значениями , не делая документацию неправильной.

$1 никогда не будет определено, потому что нет группы захвата: возможно $& (иначе$MATCH) желательно?(Или лучше, измените регулярное выражение, чтобы иметь группу захвата; -)

Счастливое кодирование.

1 голос
/ 22 октября 2011
my($foo) = $record=~ /Defect/;
print STDOUT $foo;

Вместо этого вы должны сделать

$record =~ /Defect/;
my $foo = $&; # Matched portion of the $record.

Поскольку ваша цель состоит в том, чтобы получить соответствующую часть.Возвращаемое значение - true / false, указывающее, было ли совпадение успешным или нет.

Вы можете найти http://perldoc.perl.org/perlreref.html удобным.

0 голосов
/ 22 октября 2011

Если вы хотите, чтобы результат совпадения был «истинным» или «ложным», то сопоставьте шаблон в скалярном контексте.Это то, что вы сделали в своем первом примере.Вы выполнили сопоставление с образцом и присвоили результат скаляру my ($ foo).Таким образом, $ foo получил значение «true» или «false».

Но если вы хотите захватить текст, соответствующий части вашего шаблона, используйте группирующие скобки, а затем проверьте соответствующую переменную $.Например, рассмотрим выражение:

$record =~ /(.*)ing/

Соответствие слову «говорящий» назначит «говорение» на 1 доллар, «прослушивание» назначит «прослушивание» на 1 доллар и т. Д. Это то, что вы пытаетесьсделать в вашем втором примере.Проблема в том, что вам нужно добавить в скобки группировки.«$ record = ~ / Defect /» ничего не назначит $ 1, потому что в шаблоне нет скобок для группировки.

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