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.

  1. ¿Cómo asegurarse de que la expresión regular sea global y multilínea?
  2. ¿Es mejor utilizar alguna otra opción que no sea la expresión regular incorporada?
  3. ¿Existe algún recurso en línea que enseñe expresiones regulares (bash) para completar novatos?
  4. ¿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"
¿Fue útil?

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 para sed 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 que sed 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 /'\ 
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top