Perl linha de comando regex para modificar todas as correspondências de padrões

5

Estou tentando usar alguma aritmética sobre os padrões correspondentes na linha de comando perl . Eu posso fazer isso por uma partida, mas não por todas.

str="a1b2c3"
perl -pe 's/\d+/$&+1/e'  <<<"$str"
a2b2c3

Eu entendo que $& se refere ao primeiro dígito correspondente 1 aqui. O que preciso fazer para adicionar 1 a todos os dígitos? Existe uma variável semelhante a $& que representa todos os padrões correspondentes? ou o regex precisa ser modificado para corresponder a vários dígitos.

Para a entrada dada, estou esperando algo como

a2b3c4
    
por Inian 11.11.2018 / 12:01

2 respostas

8
str="a1b2c3"
perl -pe 's/\d+/$&+1/ge' <<<"$str"

O sinalizador g para a substituição faria o Perl aplicar a expressão para cada correspondência não sobreposta na linha de entrada.

Nitpick: Na verdade, não há grupos de captura envolvidos aqui ( a questão original mencionada grupos de captura ). A variável Perl $& é a "string correspondida pela última correspondência de padrões bem-sucedida". Isto é diferente de, e. $1 e $2 etc. que se referem à cadeia correspondida pelo grupo de captura correspondente (expressão entre parênteses). Não há grupos de captura em \d+ , mas você poderia ter usado s/(\d+)/$1+1/ge , que usa um único grupo de captura.

Não há diferença entre s/(\d+)/$1+1/ge e s/\d+/$&+1/ge em termos de resultado. Neste script Perl curto e em linha, não faz diferença se você escolhe usar um ou outro, mas geralmente você gostaria de evitar usar $& em programas Perl mais longos que executam muitas operações de expressão regular, pelo menos se estiver usando uma versão mais antiga do Perl.

De perldoc perlvar (minha ênfase):

Performance issues

Traditionally in Perl, any use of any of the three variables $', $& or $' (or their use English equivalents) anywhere in the code, caused all subsequent successful pattern matches to make a copy of the matched string, in case the code might subsequently access one of those variables. This imposed a considerable performance penalty across the whole program, so generally the use of these variables has been discouraged.

[...]

In Perl 5.20.0 a new copy-on-write system was enabled by default, which finally fixes all performance issues with these three variables, and makes them safe to use anywhere.

    
por 11.11.2018 / 12:25
2

Caso você esteja realmente usando o zsh shell ( <<< é um operador não padrão que vem de zsh , mas foi copiado para alguns outros shells desde então), note que você não usa Não é necessário invocar perl para isso.

Você pode fazer:

set -o extendedglob # for (#m) below
printf '%s\n' ${str//(#m)<->/$((MATCH+1))}

Onde

  • (#m) ativa a captura de toda a correspondência em $MATCH (o equivalente a perl ' $& )
  • <-> corresponde a qualquer sequência de dígitos decimais (é como <5-12> , mas sem limite).
por 11.11.2018 / 14:04