2016-08-14 6 views
0

Следующее регулярное выражение дает мне правильные результаты при попытке в редакторе Notepad ++, но при попытке с помощью следующей программы perl я получаю неправильные результаты. Правильный ответ и объяснение, пожалуйста.регулярное выражение, которое соответствует любому слову, которое начинается с pre и заканчивается в al

Ссылка на файл я использовал для тестирования мой шаблон выглядит следующим образом:

(http://sainikhil.me/stackoverflow/dictionaryWords.txt)

Регулярное выражение: (. *)^Предварительно ал (\ S *) $

Perl программа:

use strict; 
use warnings; 

sub print_matches { 
    my $pattern = "^Pre(.*)al(\s*)\$"; 
    my $file = shift; 

    open my $fp, $file; 

    while(my $line = <$fp>) { 
     if($line =~ m/$pattern/) { 
      print $line; 
     } 
    } 
} 

print_matches @ARGV; 
+1

не избежать знака доллара –

+0

Вы уверены? Если я это сделаю, я получаю следующую ошибку. Final $ должно быть \ $ или $ name в строке ex2.pl 8, в строке синтаксическая ошибка в строке ex2.pl 8, рядом с "="^Pre (. *) Al (\ s *) $ "" – saint1729

+1

На самом деле, OP находится прямо на этом. '' 'Нужно экранировать, потому что это строка с двойными кавычками, а не шаблон регулярного выражения. ''^Pre (. *) Al (\ s *) \ $ "' (требуется экранирование) против '/^Pre (. *) Al (\ s *) $ /' (не убежать). Кстати, если вы хотите присвоить шаблон переменной как обычной строке, вам не нужно избегать '' ', если вы используете одиночные кавычки вместо двойных кавычек. –

ответ

1

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

Вот почему вам нужно избежать $, потому что в строке с двойными кавычками голый $ указывает, что вы хотите интерполировать значение переменной. (Например, my $str = "foo$bar";)

Причина это вызывает вас проблема в том, что обратная косая черта в \s рассматривается как спасаясь от s - которая дает вам просто s:

$ perl -E 'say "^Pre(.*)al(\s*)\$";' 
^Pre(.*)al(s*)$ 

В результате, когда вы перейдите для выполнения регулярного выражения, он ищет нуль или более s es, а не ноль или более символов пробелов.

Самое прямое исправление для этого было бы избежать обратной косой черты:

$ perl -E 'say "^Pre(.*)al(\\s*)\$";' 
^Pre(.*)al(\s*)$ 

Лучше исправить будет использовать одинарные кавычки вместо двойных кавычек и не избежать $:

$ perl -E "say '^Pre(.*)al(\s*)$';" 
^Pre(.*)al(\s*)$ 

Лучшим решением было бы использовать оператор qr (quote regex) вместо одиночных или двойных кавычек, хотя это делает его немного менее удобочитаемым, если вы распечатаете его позже, чтобы проверить содержимое регулярного выражения (которое я предполагаю почему ou're положить его в переменную, в первую очередь):

$ perl -E "say qr/^Pre(.*)al(\s*)$/;" 
(?^u:^Pre(.*)al(\s*)$) 

Или, конечно, просто не поставить его в переменную на всех и сделать ваше соответствие с

if($line =~ m/^Pre(.*)al(\s*)$/) ... 
+0

Привет, Дейв, спасибо за обмен знаниями. Изучив ваше объяснение, я недавно редактировал свою программу. Это показывает мне все строки вместо соответствия. Почему? – saint1729

+0

@ saint1729 - Похоже, мои последние два исправления смутили вас. Если вы присваиваете шаблон переменной, это должно быть 'my $ pattern = qr/^ Pre. * Al \ s * $ /;', а не 'm /.../'. С помощью 'm /.../' он пытается сопоставлять содержимое '$ _', не получая совпадений и присваивая' undef' '$ pattern', что затем соответствует всем. Изменение 'm /.../' на 'qr /.../' дает мне корректные результаты (Prebendal, Predial, Prejudicial, Preternatural как единственные совпадения). –

2

несколько мыслей:

  • Вы не должны бежать знак доллара
  • Захват группы вокруг непечатаемых бесполезно
  • же для захвата группы вокруг точки .

, что приводит к:

^Pre.*al\s*$ 

Если вы не хотите, чтобы слова типа precious final соответствовали (из-за среднего пробела, изменить регулярное выражение на:

^Pre\S*al\s*$ 

В коде:

while(my $line = <$fp>) { 
     if($line =~ /^Pre\S*al\s*$/m) { 
      print $line; 
     } 
    } 
1

Try удаления завершающего символа новой строки символ (ы):

while(my $line = <$fp>) { 
     $line =~ s/[\r\n]+$//s; 

и, чтобы соответствовать только словам, которые начинаются с Pre и заканчивается al, попробуйте это регулярное выражение:

/^Pre\w*al$/ 

(\w означает любую букву в слове, а не только какой-либо символ)

И, если вы хотите, чтобы соответствовать как Pre и pre, сделать регистронезависимый матч:

/^Pre\w*al$/i 
Смежные вопросы