Insertar línea después de la coincidencia usando sed

Resuelto user2150250 asked hace 11 años • 8 respuestas

Por alguna razón, parece que no puedo encontrar una respuesta sencilla a esto y estoy en un poco de poco tiempo en este momento. ¿Cómo haría para insertar una línea de texto seleccionada después de la primera línea que coincida con una cadena específica usando el sedcomando? Tengo ...

CLIENTSCRIPT="foo"
CLIENTFILE="bar"

Y quiero insertar una línea después de la CLIENTSCRIPT=línea que da como resultado...

CLIENTSCRIPT="foo"
CLIENTSCRIPT2="hello"
CLIENTFILE="bar"
user2150250 avatar Mar 22 '13 05:03 user2150250
Aceptado

Intente hacer esto usando GNU sed:

sed '/CLIENTSCRIPT="foo"/a CLIENTSCRIPT2="hello"' file

si desea sustituir in situ , utilice

sed -i '/CLIENTSCRIPT="foo"/a CLIENTSCRIPT2="hello"' file

Producción

CLIENTSCRIPT="foo"
CLIENTSCRIPT2="hello"
CLIENTFILE="bar"

Doc

  • ver sed doc y buscar \a(añadir)
Gilles Quénot avatar Mar 21 '2013 22:03 Gilles Quénot

Tenga en cuenta la sedsintaxis estándar (como en POSIX, por lo que es compatible con todas sedlas implementaciones conformes (GNU, OS/X, BSD, Solaris...)):

sed '/CLIENTSCRIPT=/a\
CLIENTSCRIPT2="hello"' file

O en una línea:

sed -e '/CLIENTSCRIPT=/a\' -e 'CLIENTSCRIPT2="hello"' file

( -eLas expresiones (y el contenido de -flos archivos) se unen con nuevas líneas para formar las sedinterpretaciones del script sed).

La -iopción para la edición in situ también es una extensión de GNU, algunas otras implementaciones (como la de FreeBSD) -i ''la admiten.

Alternativamente, para portabilidad, puedes usar perlen su lugar:

perl -pi -e '$_ .= qq(CLIENTSCRIPT2="hello"\n) if /CLIENTSCRIPT=/' file

O podrías usar edo ex:

printf '%s\n' /CLIENTSCRIPT=/a 'CLIENTSCRIPT2="hello"' . w q | ex -s file
Stephane Chazelas avatar Aug 14 '2014 10:08 Stephane Chazelas

Comando Sed que funciona tanto en MacOS (al menos, OS 10) como en Unix (es decir, no requiere gnu sed como el de Gilles (actualmente aceptado):

sed -e '/CLIENTSCRIPT="foo"/a\'$'\n''CLIENTSCRIPT2="hello"' file

Esto funciona en bash y tal vez también en otros shells que conocen el estilo de cotización de evaluación $'\n'. Todo puede estar en una línea y funcionar en comandos sed más antiguos/POSIX. Si puede haber varias líneas que coincidan con CLIENTSCRIPT="foo" (o su equivalente) y desea agregar solo la línea adicional la primera vez, puede reelaborarlo de la siguiente manera:

sed -e '/^ *CLIENTSCRIPT="foo"/b ins' -e b -e ':ins' -e 'a\'$'\n''CLIENTSCRIPT2="hello"' -e ': done' -e 'n;b done' file

(Esto crea un bucle después del código de inserción de línea que simplemente recorre el resto del archivo y nunca vuelve al primer comando sed).

Quizás notes que agregué un '^ *' al patrón coincidente en caso de que esa línea aparezca en un comentario, digamos, o tenga sangría. No es 100% perfecto, pero cubre otras situaciones que probablemente sean comunes. Ajuste según sea necesario...

Estas dos soluciones también solucionan el problema (para la solución genérica de agregar una línea) de que si su nueva línea insertada contiene barras invertidas o símbolos comerciales sin escape, sed los interpretará y probablemente no saldrán igual, como is, por \nejemplo. \0sería la primera línea coincidente. Especialmente útil si estás agregando una línea que proviene de una variable donde de otro modo tendrías que escapar de todo primero usando ${var//} antes, u otra declaración sed, etc.

Esta solución es un poco menos complicada en los scripts (aunque las comillas y \n no son fáciles de leer), cuando no desea colocar el texto de reemplazo para el comando a al comienzo de una línea, por ejemplo, en una función. con líneas sangradas. He aprovechado que el shell evalúa $'\n' como una nueva línea, no en valores normales entre comillas simples '\n'.

Sin embargo, se está haciendo lo suficientemente largo como para que creo que perl/incluso awk podría ganar debido a que es más legible.

Breezer avatar Jan 23 '2018 16:01 Breezer