regex - reemplazar - expresiones regulares espacio en blanco
¿Hay algo como una variable de contador en la expresión regular reemplazar? (1)
FMTEYEWTK sobre Fancy Regexes
Ok, voy a pasar de lo simple a lo sublime. ¡Disfrutar!
Simple s /// e Solución
Dado este:
#!/usr/bin/perl
$_ = <<"End_of_G&S";
This particularly rapid,
unintelligible patter
isn''t generally heard,
and if it is it doesn''t matter!
End_of_G&S
my $count = 0;
Luego esto:
s{
/b ( [/w'']+ ) /b
}{
sprintf "(%s)[%d]", $1, ++$count;
}gsex;
produce esto
(This)[1] (particularly)[2] (rapid)[3],
(unintelligible)[4] (patter)[5]
(isn''t)[6] (generally)[7] (heard)[8],
(and)[9] (if)[10] (it)[11] (is)[12] (it)[13] (doesn''t)[14] (matter)[15]!
Código interpolado en la solución de matriz de Anon
Mientras que esto:
s//b([/w'']+)/b/#@{[++$count]}=$1/g;
produce esto:
#1=This #2=particularly #3=rapid,
#4=unintelligible #5=patter
#6=isn''t #7=generally #8=heard,
#9=and #10=if #11=it #12=is #13=it #14=doesn''t #15=matter!
Solución con código en LHS en lugar de RHS
Esto pone el incremento dentro del mismo partido:
s/ /b ( [/w'']+ ) /b (?{ $count++ }) /#$count=$1/gx;
cede esto:
#1=This #2=particularly #3=rapid,
#4=unintelligible #5=patter
#6=isn''t #7=generally #8=heard,
#9=and #10=if #11=it #12=is #13=it #14=doesn''t #15=matter!
Una solución de solución de tartamudeo tartamudeante
Esta
s{ /b ( [/w''] + ) /b }
{ join " " => ($1) x ++$count }gsex;
genera esta deliciosa respuesta:
This particularly particularly rapid rapid rapid,
unintelligible unintelligible unintelligible unintelligible patter patter patter patter patter
isn''t isn''t isn''t isn''t isn''t isn''t generally generally generally generally generally generally generally heard heard heard heard heard heard heard heard,
and and and and and and and and and if if if if if if if if if if it it it it it it it it it it it is is is is is is is is is is is is it it it it it it it it it it it it it doesn''t doesn''t doesn''t doesn''t doesn''t doesn''t doesn''t doesn''t doesn''t doesn''t doesn''t doesn''t doesn''t doesn''t matter matter matter matter matter matter matter matter matter matter matter matter matter matter matter!
Explorando los límites
Hay enfoques más robustos para los límites de palabras que funcionan para posesivos plurales (los enfoques anteriores no), pero sospecho que su misterio radica en lograr que el ++$count
dispare, no con las sutilezas del comportamiento /b
.
Realmente me gustaría que la gente entendiera que /b
no es lo que creen que es. Siempre piensan que significa que hay espacio en blanco o el borde de la cuerda allí. Nunca lo consideran como /w/W
o /W/w
transiciones.
# same as using a /b before:
(?(?=/w) (?<!/w) | (?<!/W) )
# same as using a /b after:
(?(?<=/w) (?!/w) | (?!/W) )
Como ve, es condicional dependiendo de lo que toque. Para eso es la cláusula (?(COND)THEN|ELSE)
.
Esto se convierte en un problema con cosas como:
$_ = qq(''Tis Paul''s parents'' summer-house, isn''t it?/n);
my $count = 0;
s{
(?(?=[/-/w'']) (?<![/-/w'']) | (?<![^/-/w'']) )
( [/-/w''] + )
(?(?<=[/-/w'']) (?![/-/w'']) | (?![^/-/w'']) )
}{
sprintf "(%s)[%d]", $1, ++$count
}gsex;
print;
que imprime correctamente
(''Tis)[1] (Paul''s)[2] (parents'')[3] (summer-house)[4], (isn''t)[5] (it)[6]?
Preocuparse por Unicode
El ASCII de los años sesenta tiene unos 50 años de retraso. Así como cada vez que ves a alguien escribir [az]
, casi siempre es incorrecto, resulta que las cosas como guiones y comillas no deben aparecer como literales en los patrones, tampoco. Mientras estamos en eso, probablemente no quieras usar /w
, porque eso incluye números y guiones bajos, no solo alfabéticos.
Imagina esta cadena:
$_ = qq(/x{2019}Tis Ren/x{E9}e/x{2019}s great/x{2010}grandparents/x{2019} summer/x{2010}house, isn/x{2019}t it?/n);
que podrías tener como literal con el use utf8
:
use utf8;
$_ = qq(’Tis Renée’s great‐grandparents’ summer‐house, isn’t it?/n);
Esta vez iré al patrón de una manera un poco diferente, separando mi definición de términos de su ejecución para tratar de hacerla más legible y, por lo tanto, mantenible:
#!/usr/bin/perl -l
use 5.10.0;
use utf8;
use open qw< :std :utf8 >;
use strict;
use warnings qw< FATAL all >;
use autodie;
$_ = q(’Tis Renée’s great‐grandparents’ summer‐house, isn’t it?);
my $count = 0;
s{ (?<WORD> (?&full_word) )
# the rest is just definition
(?(DEFINE)
(?<word_char> [/p{Alphabetic}/p{Quotation_Mark}] )
(?<full_word>
# next line won''t compile cause
# fears variable-width lookbehind
#### (?<! (?&word_char) ) )
# so must inline it
(?<! [/p{Alphabetic}/p{Quotation_Mark}] )
(?&word_char)
(?:
/p{Dash}
| (?&word_char)
) *
(?! (?&word_char) )
)
) # end DEFINE declaration block
}{
sprintf "(%s)[%d]", $+{WORD}, ++$count;
}gsex;
print;
Ese código cuando se ejecuta produce esto:
(’Tis)[1] (Renée’s)[2] (great‐grandparents’)[3] (summer‐house)[4], (isn’t)[5] (it)[6]?
Ok, entonces puede que haya estado escuchando FMTEYEWTK sobre regexias sofisticadas , pero ¿no te alegra que lo hayas preguntado? ☺
Si tengo muchas coincidencias, por ejemplo, en el modo multilínea, quiero reemplazarlas con parte del partido, así como un número de contador que se incrementa.
Me preguntaba si algún sabor regex tiene esa variable. No pude encontrar uno, pero parece recordar que algo así existe ...
No estoy hablando de lenguajes de scripting en los que puedes usar callbacks para reemplazarlos. Se trata de poder hacer esto en herramientas como RegexBuddy, texto sublime, gskinner.com/RegExr, ... de la misma manera que puede referirse a las subcadenas capturadas con / 1 o $ 1.