Давайте посмотрим, как мы можем отладить эту проблему.
Ваш первый шаг должен состоять в добавлении use warnings
в ваш код. Вы должны всегда включать как use strict
, так и use warnings
. Они как сети безопасности Perl и только безрассудный программист кодирует без них.
#!/usr/bin/perl
use strict;
use warnings; # ADDED THIS
my $text='Try to find the hidden string here! Hidden or hidden';
my $a = m/\bhidden\b/;
if ($text=~ $a) {
print "I found word: $a";
}
else {
print "No match, sorry.\n";
}
Теперь мы получаем предупреждение:
Использование неинициализированного значения $ _ in соответствие шаблону (m //) в строке test_re 8.
Строка 8 выглядит следующим образом:
if ($text=~ $a) {
Итак, давайте посмотрим, что находится в $a
(в качестве отступления - пожалуйста не используйте $a
в качестве имени переменной. Во-первых, это ужасное обобщенное имя c, а во-вторых, Perl использует его как специальную переменную в функции sort
):
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say'; # ADDED THIS
my $text='Try to find the hidden string here! Hidden or hidden';
my $a = m/\bhidden\b/;
say "\$a is [$a]"; # ADDED THIS
if ($text=~ $a) {
print "I found word: $a";
}
else {
print "No match, sorry.\n";
}
Теперь, как и наше предупреждение, мы получаем следующий вывод:
$a is []
Я не думаю, что вы ожидаете, что $a
будет пустым в этот момент , ты? Мы можем go далее и определить, является ли это пустой строкой или неопределенным значением.
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my $text='Try to find the hidden string here! Hidden or hidden';
my $a = m/\bhidden\b/;
say "\$a is [$a]";
say "\$a is ", (defined $a ? 'defined' : 'undefined'); # ADDED THIS
if ($text=~ $a) {
print "I found word: $a";
}
else {
print "No match, sorry.\n";
}
И мы видим:
$a is defined
Так что это пустое строка. Что вы ожидаете, что это будет?
Вот где это установлено?
my $a = m/\bhidden\b/;
Я не уверен, что вы ожидали, что это будет делать, но на самом деле это означает "матч \bhidden\b
и присвойте результат матча $a
". И что это соответствует этому регулярному выражению? Ну, m/.../ matches the contents of
$ `по умолчанию. (Это, кстати, объясняет наше первоначальное предупреждение «неинициализированное значение $ » - Perl только что неправильно набрал номер строки на единицу.)
Так что на самом деле в этой строке происходит то, что Perl пытается сопоставить \bhidden\b
с $_
. Это терпит неудачу (так как $_
не определено), и совпадение возвращает ложное значение (пустую строку), которое присваивается $a
.
Затем ваш код запускает это:
if ($text=~ $a) {
И, поскольку $a
- пустая строка, она совпадает (любая строка будет сопоставляться с пустой строкой, а Perl сообщает, что она соответствует $a
(которая все еще содержит пустую строку).
Я не уверен, что вы пытались сделать с этой строкой:
my $a = m/\bhidden\b/;
Возможно, вы пытались каким-то образом "предварительно скомпилировать" регулярное выражение. В этом случае вы искали qr/.../
, а не m/.../
.
Так что, может быть, вы хотели это:
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my $text = 'Try to find the hidden string here! Hidden or hidden';
my $a = qr/\bhidden\b/; # CHANGED THIS
say "\$a is [$a]";
say "\$a is ", (defined $a ? 'defined' : 'undefined');
if ($text =~ $a) {
print "I found word: $a";
}
else {
print "No match, sorry.\n";
}
Что дает этот вывод:
$a is [(?^:\bhidden\b)]
$a is defined
I found word: (?^:\bhidden\b)
Или, если вы хотите показать то, что было сопоставлено, а не регулярное выражение, которое вы подходите, то вам нужно «захватить» этот текст:
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my $text = 'Try to find the hidden string here! Hidden or hidden';
my $a = qr/\b(hidden)\b/; # CHANGED THIS
say "\$a is [$a]";
say "\$a is ", (defined $a ? 'defined' : 'undefined');
if (my ($matched) = $text =~ $a) { # CHANGED THIS
print "I found word: $matched"; # CHANGED THIS
}
else {
print "No match, sorry.\n";
}
, что дает нам:
$a is [(?^:\b(hidden)\b)]
$a is defined
I found word: hidden
Ах, но вы хотите увидеть все слова, поэтому запишите совпадения в массив и используйте параметр /g
, чтобы сопоставить несколько Несколько раз:
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my $text = 'Try to find the hidden string here! Hidden or hidden';
my $a = qr/\b(hidden)\b/;
say "\$a is [$a]";
say "\$a is ", (defined $a ? 'defined' : 'undefined');
if (my (@matched) = $text =~ /$a/g) { # CHANGED THIS
print "I found word: @matched"; # CHANGED THIS
}
else {
print "No match, sorry.\n";
}
Теперь мы получаем это:
$a is [(?^:\b(hidden)\b)]
$a is defined
I found word: hidden hidden
Это соответствует только двум экземплярам «скрытого», поскольку совпадение чувствительно к регистру. Так что отключите чувствительность к регистру с помощью /i
.
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my $text = 'Try to find the hidden string here! Hidden or hidden';
my $a = qr/\b(hidden)\b/i; # CHANGED THIS
say "\$a is [$a]";
say "\$a is ", (defined $a ? 'defined' : 'undefined');
if (my (@matched) = $text =~ /$a/g) {
print "I found word: @matched";
}
else {
print "No match, sorry.\n";
}
, что дает нам:
$a is [(?^i:\b(hidden)\b)]
$a is defined
I found word: hidden Hidden hidden
Но, честно говоря, я думаю, предварительно скомпилировав регулярное выражение здесь просто усложняются вещи. Я написал бы этот код следующим образом (полностью удаляя переменную $a
):
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my $text = 'Try to find the hidden string here! Hidden or hidden';
if (my (@matched) = $text =~ /\b(hidden)\b/gi) {
print "I found word: @matched";
}
else {
print "No match, sorry.\n";
}