Двухэтапное сопоставление регулярного выражения с переменной в Perl - PullRequest
2 голосов
/ 01 ноября 2011

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

here is some text 9337 more text AA 2214 and some 1190 more BB stuff 8790 words

У меня также есть хэш со следующими значениями:

%my_hash = ( 9337 => 'AA', 2214 => 'BB', 8790 => 'CC' );

Вот что мне нужно сделать:

  1. Найти номер
  2. Найти текстовый код для номера с помощью my_hash
  3. Проверитьесли текстовый код появляется в пределах 50 символов от идентифицированного числа, и если true, выведите результат

Итак, я ищу вывод:

Found 9337, matches 'AA'
Found 2214, matches 'BB'
Found 1190, no matches
Found 8790, no matches

Вот что ядо сих пор:

while ( $text =~ /(\d+)(.{1,50})/g ) {
  $num = $1;
  $text_after_num = $2;
  $search_for = $my_hash{$num};
  if ( $text_after_num =~ /($search_for)/ ) {
    print "Found $num, matches $search_for\n";
  }
  else {
   print "Found $num, no matches\n";
  }

Такого рода работы, за исключением того, что единственное правильное совпадение - 9337;код не соответствует 2214. Я думаю, что причина в том, что совпадение регулярного выражения в 9337 включает 50 символов после числа для совпадения второго шага, а затем, когда механизм регулярных выражений запускается снова, он запускается с точки после точки2214. Есть ли простой способ это исправить?Я думаю, что модификатор \G может помочь мне здесь, но я не совсем понимаю, как.

Любые предложения или помощь будут великолепны.

Ответы [ 2 ]

3 голосов
/ 01 ноября 2011

У вас проблема с жадностью. 1,50 будет потреблять столько, сколько может. Ваше регулярное выражение должно быть /(\d+)(.+?)(?=($|\d))/

Чтобы объяснить, вопросительный знак сделает множественное совпадение нежадным (оно остановится, как только будет сопоставлен следующий шаблон - следующий шаблон получает приоритет). ?= является оператором предварительного просмотра, который говорит: «Проверьте, является ли следующий элемент цифрой. Если это так, сопоставьте, но не используйте». Это позволяет получить первую цифру к началу регулярного выражения и поместить ее в следующий соответствующий шаблон.

[EDIT] Я добавил необязательное конечное значение для просмотра, чтобы оно не погибало при последнем совпадении.

2 голосов
/ 01 ноября 2011

Просто используйте:

/\b\d+\b/g

Зачем сочетать все, если вам не нужно?Вы должны использовать другие функции, чтобы определить, где находится число:

/(?=9337.{1,50}AA)/

Это не удастся, если АА будет дальше 50 символов от конца 9337. Конечно, вам придется интерполировать ваши переменные в соответствии с ключами и значениями вашего хэша.Это был просто пример для вашей первой пары ключ / значение.

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