Referências retroativas a constituintes de um grupo que consiste em um número fixo de repetições

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

Pergunta

Quero encontrar um grupo que se repita x vezes um após o outro, por exemplo, cinco vezes uma combinação de letras e dígitos separada por um espaço.Posso usar uma sintaxe de repetição simples, por exemplo (?:\w\d ){5}.

Quero então substituir o espaço neste dígito de 5 letras por outra coisa.Para isso, tento fazer referência retroativa a cada uma das combinações de letras e dígitos (sem espaço) colocando parênteses: (?:(\w\d) ){5}.Infelizmente, todos os cinco estão armazenados em $1, ou seja, $1 é substituído toda vez que corresponde.

Então, existe uma maneira de evitar essa substituição?Ou existe uma maneira de substituir algo apenas em uma substring?

EDITAR:

Exemplo de string de entrada: A1 A3 A4 B6 ::: A1 A3 A4 C5 B6

String de saída desejada: A1 A3 A4 B6 ::: A1-A3-A4-C5-B6

Isso significa substituir o espaço somente se houver cinco deles.Implementado em Perl.

Foi útil?

Solução

Se você quer apenas resolver o problema, algo assim funciona

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

Caso contrário, a repetição de grupo em Perl sobrescreve o buffer de captura a cada loop.

Não sei se outra forma programática é possível.

editar

Se você quiser cobrir vários espaços entre caracteres, adicione um quantificador + e o tr ///s - esmagar substituições duplicadas em tr ///.
s/(\w\d(?: +\w\d){4})/$_=$1; tr{ }{-}s; $_/eg;

Se você tiver substituições mais sofisticadas, poderá sempre duplicar o regex com um estilo de retorno de chamada
equivalente

$string =~ s/(\w\d(?: +\w\d){4})/fixspaces($1)/eg;
sub fixspaces {
   my $buf = shift;
   $buf =~ s/ +/-/g;
   $buf;
}

Outras dicas

É feio e inflexível, mas para a sua entrada de amostra, se realmente for sempre cinco, e se a sua entrada de amostra nunca variar, isso deve funcionar:

s/(\w\d) +(\w\d) +(\w\d) +(\w\d) +(\w\d) */$1-$2-$3-$4-$5/

Isso funciona:

#!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;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top