regex - reemplazar - expresiones regulares ejemplos
¿Puedo sustituir varios elementos en una sola expresión regular en VIM o Perl? (7)
En perl:
s/quick(.*)lazy/slow${1}energetic/;
En vim:
s/quick/(.*/)lazy/slow/1energetic/;
Digamos que tengo una cuerda "El zorro café rápido salta sobre el perro perezoso" ¿Puedo cambiar esto a "El zorro marrón lento salta sobre el perro energético" con una expresión regular? Actualmente, utilizo dos conjuntos de expresiones regulares para esta situación. (En este caso, uso s/quick/slow/
seguido de s/lazy/energetic/
).
Hay una buena manera de hacerlo en Ruby usando gsub con un bloque:
s = "The quick brown fox jumps over the lazy dog"
subs = {''quick'' => ''slow'', ''lazy'' => ''industrious''}
s.gsub(/quick|lazy/) { |match| subs[match] }
# => "The slow brown fox jumps over the industrious dog"
La respuesta de Chas es buena, la única otra cosa que mencionaría es que si estás haciendo intercambios de palabras probablemente quieras hacer coincidir
/ b (foo | bar | baz | qux) / b
para evitar la coincidencia de subcadenas. Si haces un gran intercambio de palabras, podrías comenzar a encontrar expresiones regulares un poco limitantes y quieres hacer algo como:
join '''', map { exists $subst{$_} ? $subst{$_} : $_ } split //b/, $string
La segunda parte de una sustitución es una cadena entre comillas dobles, por lo que puede ocurrir cualquier interpolación normal. Esto significa que puede usar el valor de la captura para indexar en un hash:
#!/usr/bin/perl
use strict;
use warnings;
my %replace = (
quick => "slow",
lazy => "energetic",
);
my $regex = join "|", keys %replace;
$regex = qr/$regex/;
my $s = "The quick brown fox jumps over the lazy dog";
$s =~ s/($regex)/$replace{$1}/g;
print "$s/n";
Puede concatenar sustituciones vim:
El rápido zorro marrón corrió rápidamente al lado del arroyo perezoso.
:s/quick/slow/|s/lazy/energetic/
El lento zorro marrón corría rápidamente al lado del arroyo energético.
La ventaja aquí es que tienes que escribir tus sustituciones solo una vez
Rgds
Puedes hacer esto en vim usando un Diccionario:
:%s/quick/|lazy//={''quick'':''slow'',''lazy'':''energetic''}[submatch(0)]/g
Esto cambiará el siguiente texto:
El rápido zorro marrón corría rápidamente junto al arroyo perezoso .
dentro:
El lento zorro marrón corría lentamente junto al arroyo energético .
Para ver cómo funciona esto, consulte :help sub-replace-expression
y :help Dictionary
. En breve,
-
/=
te permite sustituir el resultado de una expresión vim. -
{''quick'':''slow'', ''lazy'':''energetic''}
es un diccionario vim (como un hash en perl o ruby, o un objeto en javascript) que usa[]
para búsquedas. -
submatch(0)
es la cadena coincidente
Esto puede ser útil cuando refactorice el código; digamos que desea intercambiar los nombres de las variables para cambiar foo
, bar
y baz
-
foo
→bar
-
bar
→baz
-
baz
→foo
Usar una secuencia de comandos %s///
sería complicado, a menos que use nombres temporales de variables, pero debe asegurarse de que no estén golpeando nada más. En cambio, puede usar un diccionario para hacerlo en una sola pasada:
:%s//</%(foo/|bar/|baz/)/>//={''foo'':''bar'',''bar'':''baz'',''baz'':''foo''}[submatch(0)]/g
Lo cual cambia este código
int foo = 0;
float bar = pow(2.0, (float) foo);
char baz[256] = {};
sprintf(baz,"2^%d = %f/n", foo, bar);
dentro:
int bar = 0;
float baz = pow(2.0, (float) bar);
char foo[256] = {};
sprintf(foo,"2^%d = %f/n", bar, baz);
Si te encuentras haciendo esto mucho, puedes agregar lo siguiente a tu ~/.vimrc
:
" Refactor the given lines using a dictionary
" replacing all occurences of each key in the dictionary with its value
function! Refactor(dict) range
execute a:firstline . '','' . a:lastline . ''s//C/</%('' . join(keys(a:dict),''/|''). ''/)/>//=''.string(a:dict).''[submatch(0)]/ge''
endfunction
command! -range=% -nargs=1 Refactor :<line1>,<line2>call Refactor(<args>)
Esto le permite usar el :Refactor {''frog'':''duck'', ''duck'':''frog''}
, y es ligeramente menos repetitivo que crear la expresión regular para el dict manualmente.
Puedes hacer lo siguiente.
:%s/quick/(.*/)lazy/slow/1energetic
El truco es usar los parens para hacer coincidir el texto entre las dos palabras. A continuación, puede hacer referencia a este texto en la cadena de sustitución utilizando /1
. También puede usar /2
para la segunda expresión paren coincidente y así sucesivamente. Esto le permite reemplazar varias palabras sin alterar el texto entre ellas.