Referências retroativas a constituintes de um grupo que consiste em um número fixo de repetições
-
14-12-2019 - |
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.
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;