Как я могу сохранить пробелы при сопоставлении и заменить несколько слов в Perl? - PullRequest
1 голос
/ 15 сентября 2009

Допустим, у меня есть оригинальный текст:

here is some text that has a substring that I'm interested in embedded in it.

Мне нужно, чтобы текст соответствовал его части, скажем: "has a substring".

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

has a
substring

или

has  a substring

и / или оригинальный текст может быть:

here is some
text that has
a substring that I'm interested in embedded in it.

Что мне нужно для вывода моей программы:

here is some text that [match starts here]has a substring[match ends here] that I'm interested in embedded in it.

Мне также нужно сохранить шаблон пробела в оригинале и просто добавить к нему маркеры начала и конца.

Есть идеи о том, как использовать регулярные выражения Perl, чтобы это произошло? Я пытался, но в конечном итоге запутался.

Ответы [ 5 ]

5 голосов
/ 15 сентября 2009

Прошло некоторое время с тех пор, как я использовал регулярные выражения Perl, но как насчет:

$match = s/(has\s+a\s+substring)/[$1]/ig

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

Вы можете играть в игры с этим, например, взять строку "has a substring" и выполнить преобразование, чтобы сделать ее "has\s*a\s*substring", чтобы сделать это немного менее болезненным.

РЕДАКТИРОВАТЬ : Включены комментарии Ysth о том, что метасимвол \ s соответствует символам новой строки и исправлениям Хоббса в моем использовании.

3 голосов
/ 15 сентября 2009

Этот шаблон будет соответствовать строке, которую вы ищете, чтобы найти:

(has\s+a\s+substring)

Итак, когда пользователь вводит строку поиска, замените все пробелы в строке поиска на \s+, и у вас есть шаблон. Просто замените каждое совпадение на [match starts here]$1[match ends here], где $1 - это совпадающий текст.

2 голосов
/ 15 сентября 2009

В регулярных выражениях вы можете использовать + для обозначения «один или несколько». Так что-то вроде этого

/has\s+a\s+substring/

соответствует has, за которым следуют один или несколько пробельных символов, затем a, за которыми следуют один или несколько пробельных символов, после которых substring.

Соединяя его с оператором подстановки, вы можете сказать:

my $str = "here is some text that has     a  substring that I'm interested in embedded in it.";
$str =~ s/(has\s+a\s+substring)/\[match starts here]$1\[match ends here]/gs;

print $str;

И вывод:

here is some text that [match starts here]has     a  substring[match ends here] that I'm interested in embedded in it.
0 голосов
/ 15 сентября 2009

Это пример того, как вы могли бы сделать это.

#! /opt/perl/bin/perl
use strict;
use warnings;

my $submatch = "has a\nsubstring";

my $str = "
here is some
text that has
a substring that I'm interested in, embedded in it.
";

print substr_match($str, $submatch), "\n";

sub substr_match{
  my($string,$match) = @_;

  $match =~ s/\s+/\\s+/g;

  # This isn't safe the way it is now, you will need to sanitize $match
  $string =~ /\b$match\b/;
}

В настоящее время это ничего не делает для проверки переменной $match на наличие небезопасных символов.

0 голосов
/ 15 сентября 2009

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

my $original = "here is some text that has a substring that I'm interested in embedded in it.";
my $search = "has a\nsubstring";

my $re = $search;
$re =~ s/\s+/\\s+/g;

$original =~ s/\b$re\b/[match starts here]$&[match ends here]/g;

print $original;

Выход:

here is some text that [match starts here]has a substring[match ends here] that I'm interested in embedded in it.

Возможно, вы захотите экранировать любые метасимволы в строке. Если кому-то интересно, я мог бы добавить это.

...