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

StackOverflow https://stackoverflow.com/questions/1425023

  •  07-07-2019
  •  | 
  •  

Вопрос

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

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, чтобы это произошло?Я пытался, но в итоге ужасно запутался.

Это было полезно?

Решение

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

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

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

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

Редактировать:Включены комментарии ysth о том, что метасимвол \ s соответствует переводу строк и исправлениям Хоббса в моем использовании.

Другие советы

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

(has\s+a\s+substring)

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

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

/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.

Многие предлагали, использовать \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.

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

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

#! /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 переменная для небезопасных символов.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top