Обратные ссылки на составляющие группы, состоящие из фиксированного количества повторений - PullRequest
2 голосов
/ 15 марта 2012

Я хочу найти группу, которая повторяется x раз друг за другом, например, пять раз комбинация букв и цифр, разделенных пробелом. Я могу использовать простой синтаксис повторения, например (?:\w\d ){5}.

Затем я хочу заменить пробел в 5-буквенной цифре чем-то другим. Для этого я пытаюсь сделать обратную ссылку на каждую комбинацию букв и цифр (без пробела), поместив вокруг нее скобки: (?:(\w\d) ){5}. К сожалению, все пять хранятся в $1, т. Е. $1 перезаписывается при каждом совпадении.

Итак, есть ли способ избежать этой перезаписи? Или есть способ заменить что-то только в подстроке?

EDIT:

Пример входной строки: A1 A3 A4 B6 ::: A1 A3 A4 C5 B6

Желаемая строка вывода: A1 A3 A4 B6 ::: A1-A3-A4-C5-B6

Это значит, заменить пространство, только если их пять. Реализовано в Perl.

Ответы [ 3 ]

3 голосов
/ 15 марта 2012

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

s/(\w\d) +(\w\d) +(\w\d) +(\w\d) +(\w\d) */$1-$2-$3-$4-$5/
2 голосов
/ 15 марта 2012

Если вы просто хотите решить проблему, что-то вроде этого работает

$string = 'A1 A3 A4 B6 ::: A1 A3 A4 C5 B6';
$string =~ s/(\w\d(?: \w\d){4})/$_=$1; tr{ }{-}; $_/eg;
print "'$string'\n";

В противном случае групповое повторение в Perl делаетперезаписывать буфер захвата каждый цикл.

Я не знаю, возможен ли другой программный способ.

edit

Если вы хотите закрыть несколько пробелов между символами, добавьте +квантификатор и tr /// s - двойные замены в сквоше в tr ///.
s/(\w\d(?: +\w\d){4})/$_=$1; tr{ }{-}s; $_/eg;

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

$string =~ s/(\w\d(?: +\w\d){4})/fixspaces($1)/eg;
sub fixspaces {
   my $buf = shift;
   $buf =~ s/ +/-/g;
   $buf;
}
0 голосов
/ 15 марта 2012

Это работает:

#!usr/bin/perl
sub substitute{
    $substr=shift;
$substr=~s/\s/-/gi;
return $substr;
}

$test="hello a1 b2 c3 d4 e5 testing";
$test=~s/((?:\w\d\s){4})(\w\d)\s/&substitute($1).$2." "/egi;
print $test;
...