El problema es encontrar los códigos que comienzan por 12. En negrita
se han resaltado las soluciones. Son soluciones sólo aquellas que, comienzan
por 12
en una posición múltiplo de seis.
Una solución es:
@nums = grep {m/^12/} m/\d{6}/g;
que genera una lista con los números y luego selecciona los que comienzan por
12
.
Otra solución es:
@nums = grep { defined } m/(12\d{4})|\d{6}/g;
que aprovecha que la expresión regular devolverá una lista vacía cuando
el número no empieza por 12
:
DB<1> $x = '012345678901123334234567890123125934890123345126' DB<2> x ($x =~ m/(12\d{4})|\d{6}/g) 0 undef 1 undef 2 123334 3 undef 4 undef 5 125934 6 undef 7 undefObsérvese que se esta utilizando también que el operador
|
no es greedy.
¿Se puede resolver el problema usando sólamente una expresión regular? Obsérvese que esta solución ``casi funciona'':
DB<3> x @nums = $x =~ m/(?:\d{6})*?(12\d{4})/g; 0 123334 1 125934 2 123345
recoge la secuencia mas corta de grupos de seis dígitos que no casan, seguida
de una secuencia que casa.
El problema que tiene esta solución
es al final, cuando se han casado todas las soluciones, entonces
la búsqueda exhaustiva hará que nos muestre soluciones que no comienzan en posiciones
múltiplo de seis. Por eso encuentra 123345
:
@nums = m/(?:\d{6})*?(12\d{4})(?:(?!12)\d{6})*/g;
Se asume que existe al menos un éxito en la entrada inicial. Que es un extraordinario ejemplo de como el uso de paréntesis de agrupamiento simplifica y mejora la legibilidad de la solución. Es fantástico también el uso del operador de predicción negativo.
El ancla \G
ha sido concebida para su uso con la opción /g
.
Casa con el punto en la cadena en el que terminó el último emparejamiento.
Cuando se trata del primer intento o no se está usando /g
, usar \G
es lo mismo que usar \A
.
Mediante el uso de este ancla es posible formular la siguiente solución al problema planteado:
pl@nereida:~/Lperltesting$ perl -wde 0 main::(-e:1): 0 DB<1> $_ = '012345678901123334234567890123125934890123345126' DB<2> x m/\G(?:\d{6})*?(12\d{4})/g 0 123334 1 125934
Si lo que se quiere es sustituir las secuencias deseadas es poisble hacerlo con la siguiente expresión regular:
casiano@nereida:~/docs/curriculums/CV_MEC$ perl -wde 0 DB<1> x $x = '012345678901123334234567890123125934890123345126' 0 012345678901123334234567890123125934890123345126 DB<2> x ($y = $x) =~ s/(12\d{4})|\d{6}/$1? "-$1-":$& /ge 0 8 DB<3> p $y 012345678901-123334-234567890123-125934-890123345126