Traducir la sustitución de expresiones regulares de RegEXR para que funcione en el script bash
-
21-12-2019 - |
Pregunta
Estoy intentando crear un comando de sustitución de expresiones regulares en un script bash, pero después de jugar con comillas simples, comillas dobles y caracteres de escape, me estoy arrancando los pelos.Utilizo RegEXR para componer patrones y se me ocurrió lo siguiente:
busco:
/\.icon-(.*) {\n\t/gm
y quiero reemplazarlo con:
if(strpos(\$embedicons,'$1') !== false) { \$svgicons .= <<<'EOD'\n\.$1 {
Esto reemplaza esto:
.icon-basket-14-icon {
background-image: url('data:image/svg+xml;charset=US-ASCII,blahblah');
background-repeat: no-repeat;
}
con este:
if(strpos($embedicons,'basket-14-icon') !== false) { $svgicons .= <<<'EOD'
.basket-14-icon {background-image: url('data:image/svg+xml;charset=US-ASCII,blahblah');
background-repeat: no-repeat;
}
Sin embargo, no logro lograr que esto suceda dentro de un script bash.No estoy seguro de que sea relevante, pero estoy en OSX Mavericks y uso la aplicación Terminal.Si bien los patrones en RegExr tienen sentido para mí, una vez que empiezo a escapar de ellos, pierdo por completo la noción de lo que está sucediendo.
- ¿Cómo asegurarse de que la expresión regular sea global y multilínea?
- ¿Es mejor utilizar alguna otra opción que no sea la expresión regular incorporada?
- ¿Existe algún recurso en línea que enseñe expresiones regulares (bash) para completar novatos?
- ¿Existe un patrón grupal que coincida con todo (incluido el espacio en blanco y las nuevas líneas) hasta que una cadena de caracteres dada como un asterisco (*)?
Obviamente no estoy buscando limosna, ya que este problema me persigue regularmente...Me encantaría aprender expresiones regulares y resolver mis problemas aprendiendo y estudié algunos ejemplos en línea, pero parecen demasiado avanzados.¿Quizás exista un generador en línea como RegExr que se traduzca en versiones de patrones de expresiones regulares compatibles con bash y PHP?
ACTUALIZACIÓN/SOLUCIÓN:
Lo siguiente parece funcionar para mí en la terminal OSX Mavericks:
sed "s|\.icon-\(.*\) {|if(strpos(\$embedicons,'\1') !== false) { \$svgicons \.= <<<'EOD' \.\1 {|g"
Solución
Yo sugeriría usar sed
para este tipo de reemplazo, esta línea hará lo que quieras:
sed "s/^.icon-\(.*\) {$/if(strpos(\$embedicons,'\1') !== false) { \$svgicons .= <<<'EOD'\n.\1 {/"g input_file.txt
archivo_entrada.txt:
.icon-basket-14-icon {
background-image: url('data:image/svg+xml;charset=US-ASCII,blahblah');
background-repeat: no-repeat;
}
Producción:
if(strpos($embedicons,'basket-14-icon') !== false) { $svgicons .= <<<'EOD'
.basket-14-icon {
background-image: url('data:image/svg+xml;charset=US-ASCII,blahblah');
background-repeat: no-repeat;
}
Con el -r
(expresión regular extendida), solo necesita escapar de las llaves literales y los signos de dólar variables en su ejemplo.
Con respecto a tus preguntas:
- el
g
bandera parased
lo hace global.¿Qué quieres decir exactamente con "multilínea"?Generar nuevas líneas es fácil usando , hacer coincidir líneas es un poco más complejo ya quesed
opera línea por línea.Una técnica común es reemplazar todas las líneas nuevas en el archivo/datos con un marcador de posición, realizar la expresión regular/sustitución con el marcador de posición en mente y luego reemplazar el marcador de posición con líneas nuevas nuevamente. sed
es probablemente tu mejor opción para cosas de tipo regex.Puede encontrar documentación en línea, que es bastante completa: http://www.grymoire.com/Unix/Sed.html
Para la última parte, usando (.*)
capturará todo, luego solo tiene que manejar las nuevas líneas y asegurarse de escapar correctamente de la cadena de terminación.
archivo de prueba:
testing data with space -
and newlines /'\ *** ends
there
Dominio (tr
está intercambiando nuevas líneas por tildes y viceversa):
tr '\n' '~' < testfile | sed -r 's/(.*)\*\*\*.*/\1/g' | tr '~' '\n'
Producción:
testing data with space -
and newlines /'\