2012-01-03 14 views
8

Quiero editar un archivo mediante un script sed en un script bash. Quiero que esto sea fácil de mantener más tarde; fácil de entender y modificar La cadena de reemplazo se ve así:¿Cómo puedo escapar de las barras diagonales inversas en un script sed incrustado en un script bash?

PS1='\[\e[1;32m\][\[email protected]\h \W]\$\[\e[0m\]' 

En un mundo perfecto, que desea:

sed -i "s/^PS1.*$/PS1='\[\e[1;32m\][\[email protected]\h \W]\$\[\e[0m\]'/g" /etc/skel/.bashrc 

El problema es que bash y SED se Excluyendo el \ dando el siguiente resultado en el archivo:

PS1='[e[1;32m][@h W]$[e[0m]' 

Obviamente no se pueden utilizar comillas simples. Una solución de fuerza bruta es el uso de los escapes, pero para que esto funcione me sale una línea que parece muy feo:

sed -i "s/^PS1.*$/PS1='\\\\[\\\\e[1;32m\\\\][\\\\[email protected]\\\\h \\\\W]\\\\$\\\\[\\\\e[0m\\\\]'/g" /etc/skel/.bashrc 

que desea que el script se pueda leer y autónomo (no usar archivos externos). ¿Alguna alternativa a la anterior?

+0

Usa comillas simples alrededor de algo como una expresión regular a menos que necesites absolutamente alguna variable interpolada en la cadena. Incluso entonces, use comillas simples para la mayoría de las expresiones regulares, y solo use las comillas dobles alrededor de la parte que debe ser interpolada. Usando un ejemplo inventado: 'sed-e 's /\.\*'"$ 1"' \ * \ ./ ab '"$ 2"' c '\' 'd /' $ 3' o algo similar. La secuencia ''\' '' es cómo incrusta una comilla simple en la línea de comando; la primera cotización individual termina la sección actual de una sola cotización; la comilla invertida inserta una comilla simple en la cadena; la tercera cita individual resume la comilla simple. –

Respuesta

5

La impresión de Bash puede agregar los escapes necesarios, dejando que la cadena se inserte de forma legible y editable.

sed -i "s/^PS1.*$/$(printf "%q" "PS1='\[\e[1;32m\][\[email protected]\h \W]$\[\e[0m\]'")/g" /etc/skel/.bashrc 

No tratar de pegar todo en una sola línea hace que todo sea más claro.

REPL=$(printf "%q" "PS1='\[\e[1;32m\][\[email protected]\h \W]$\[\e[0m\]'") 
sed -i "s/^PS1.*$/$REPL/g" /etc/skel/.bashrc 
1

Utilice un archivo de script sed con sed -f. Esta alternativa tampoco es bonita, ya que significa tener un archivo adicional por ahí, pero al menos evita los escapes de shell.

+0

No desea utilizar archivos externos. – hauptmech

+0

Puede utilizar un documento aquí con algunas implementaciones 'sed', es decir,' sed -f - << 'EOF'' – tripleee

4

Esto podría funcionar para usted:

echo "PS1=abc" | 
sed 's/^PS1.*$/PS1='\''\\[\\e[1;32m\\][\\[email protected]\\h \\W]\\$\\[\\e[0m\\]'\''/' 
PS1='\[\e[1;32m\][\[email protected]\h \W]\$\[\e[0m\]' 
+0

+1 comillas simples es el camino a seguir. – tripleee

+0

Encuentro las comillas simples difíciles de distinguir, además de que la cadena de reemplazo debe escaparse, lo que hace que sea un poco difícil de leer. – hauptmech

1

¿Qué tal esto:

sed -i 's/^PS1.*$/PS1=SINGLEQUOTESLASH[SLASHe[1;32mSLASH][[email protected] SLASHW]SLASH$SLASH[SLASHe[0mSLASH]SINGLEQUOTE/g' /etc/skel/.bashrc 
sed -i "s/SINGLEQUOTE/'/g" /etc/skel/.bashrc 
sed -i "s/SLASH/\\/g" /etc/skel/.bashrc 

Hacerlo en dos pases es menos eficiente, pero un poco más de microsegundos es imperceptible para la mayoría de la gente.

+0

Me gusta a dónde va esto, pero sed necesita que el \ 's escapó ... por lo que realmente no produce la salida deseada. – hauptmech

+0

@hauptmech Lo he editado para usar SLASH en lugar de '\'. Se ve un poco menos legible ahora sin embargo. Puede ser mejor usar Python o Perl –

Cuestiones relacionadas