Inserte una línea en un número de línea específico con sed o awk


146

Tengo un archivo de script que necesito modificar con otro script para insertar un texto en la octava línea.

Cadena para insertar:, Project_Name=sowstesten un archivo llamado start.

Traté de usar awk y sed, pero mi comando se está confundiendo.

Respuestas:


231
sed -i '8i8 This is Line 8' FILE

insertos en la línea 8

8 This is Line 8

en el archivo ARCHIVO

-i realiza la modificación directamente al archivo ARCHIVO, sin salida a stdout, como se menciona en los comentarios de Glenn Jackman.


3
Sí, el modificador -i es específico para GNU-sed.
usuario desconocido

1
No. -i significa "modificar el archivo especificado en su lugar". Insertar vs. anexar se logra con '8isomething' vs. '8asomething', independiente del interruptor -i.
usuario desconocido el

11
usuarios de mac: con homebrew, brew install gnu-sedy luego usen esto congsed
cwd

44
¡Esto es súper útil! ¿Hay alguna forma de insertar espacios al principio de la línea? Noté SED no está prestando atención a los espacios en blanco inicial ...
elju

9
@elju: Sí, enmascararlo con una barra invertida: sed '8i\ 8 This is Line 8' FILE.
usuario desconocido


19

OS X / macOS / FreeBSD sed

La -ibandera funciona de manera diferente en macOS sedque en GNU sed.

Aquí está la forma de usarlo en macOS / OS X:

sed -i '' '8i\
8 This is Line 8' FILE

Ver man 1 sedpara más información.


18

la respuesta awk

awk -v n=8 -v s="Project_Name=sowstest" 'NR == n {print s} {print}' file > file.new

@glenn jackman Necesito ingresar #define SERVER@"http://10.35.42.54/ms0.8"a una línea en particular. ¿Cómo puedo conseguir esto?
Nevin Raj Victor

1
Creo que Nevin solo necesita escapar de las comillas en su cadena con barras invertidas
Chris Koknat

@waLLe, comience con la página de información de awk que tiene una buena descripción de cómo funciona awk. Aquí, tengo 2 pares "condición {acción}", el segundo no tiene condición, lo que significa que la acción se realiza para cada registro. Después de que termine de leer y aún tenga preguntas, avíseme.
Glenn Jackman

@glennjackman casi allí ... simplemente no entendí esto: archivo> archivo.nuevo
w411 3 de

"archivo" representa el nombre del archivo en el que está trabajando awk. >es el símbolo de redirección de shell para que la salida de awk se almacene en el archivo llamado "file.new".
Glenn Jackman

16

POSIX sed(y, por ejemplo, OS X sed, los sedsiguientes) ideben ir seguidos de una barra diagonal inversa y una nueva línea. Además, al menos OS X sedno incluye una nueva línea después del texto insertado:

$ seq 3|gsed '2i1.5'
1
1.5
2
3
$ seq 3|sed '2i1.5'
sed: 1: "2i1.5": command i expects \ followed by text
$ seq 3|sed $'2i\\\n1.5'
1
1.52
3
$ seq 3|sed $'2i\\\n1.5\n'
1
1.5
2
3

Para reemplazar una línea, puede usar los comandos c(cambiar) o s(sustituir) con una dirección numérica:

$ seq 3|sed $'2c\\\n1.5\n'
1
1.5
3
$ seq 3|gsed '2c1.5'
1
1.5
3
$ seq 3|sed '2s/.*/1.5/'
1
1.5
3

Alternativas usando awk:

$ seq 3|awk 'NR==2{print 1.5}1'
1
1.5
2
3
$ seq 3|awk '{print NR==2?1.5:$0}'
1
1.5
3

awkinterpreta las barras diagonales inversas en las variables pasadas con, -vpero no en las variables pasadas usando ENVIRON:

$ seq 3|awk -v v='a\ba' '{print NR==2?v:$0}'
1
a
3
$ seq 3|v='a\ba' awk '{print NR==2?ENVIRON["v"]:$0}'
1
a\ba
3

Ambos ENVIRONy -vestán definidos por POSIX.


7

Soluciones Perl:

rápido y sucio:

perl -lpe 'print "Project_Name=sowstest" if $. == 8' file

  • -l elimina las nuevas líneas y las agrega nuevamente, eliminando la necesidad de "\ n"
  • -p recorre el archivo de entrada, imprimiendo cada línea
  • -e ejecuta el código entre comillas simples

$. es el número de línea

equivalente a la solución awk de @ glenn, utilizando argumentos con nombre:

perl -slpe 'print $s if $. == $n' -- -n=8 -s="Project_Name=sowstest" file

  • -s permite un analizador de argumentos rudimentario
  • -- evita que -n y -s sean analizados por el analizador de argumentos perl estándar

argumentos de comando posicional:

perl -lpe 'BEGIN{$n=shift; $s=shift}; print $s if $. == $n' 8 "Project_Name=sowstest" file

Variables de entorno:

setenv n 8 ; setenv s "Project_Name=sowstest"
echo $n ; echo $s
perl -slpe 'print $ENV{s} if $. == $ENV{n}' file

ENV es el hash que contiene todas las variables de entorno

Getopt para analizar argumentos en hash% o:

perl -MGetopt::Std -lpe 'BEGIN{getopt("ns",\%o)}; print $o{s} if $. == $o{n}' -- -n 8 -s "Project_Name=sowstest" file

Getopt :: Nombres de opciones largos y más largos

perl -MGetopt::Long -lpe 'BEGIN{GetOptions(\%o,"line=i","string=s")}; print $o{string} if $. == $o{line}' -- --line 8 --string "Project_Name=sowstest" file

Getopt es la solución de biblioteca estándar recomendada.
Esto puede ser excesivo para los scripts de Perl de una línea, pero se puede hacer


2
Felicitaciones a Chris por tomarse el tiempo para explicar todo eso y exponerlo tan bien, pero wow, esta es la razón por la que no me gusta Perl.
rsaw

5

Para aquellos que están en SunOS que no es GNU, el siguiente código ayudará:

sed '1i\^J
line to add' test.dat > tmp.dat
  • ^ J se inserta con ^ V + ^ J
  • Agregue la nueva línea después de '1i.
  • \ DEBE ser el último carácter de la línea.
  • La segunda parte del comando debe estar en una segunda línea.

5

sed -e '8iProject_Name=sowstest' -i start usando GNU sed

Ejecución de muestra:

[root@node23 ~]# for ((i=1; i<=10; i++)); do echo "Line #$i"; done > a_file
[root@node23 ~]# cat a_file
Line #1
Line #2
Line #3
Line #4
Line #5
Line #6
Line #7
Line #8
Line #9
Line #10
[root@node23 ~]# sed -e '3ixxx inserted line xxx' -i a_file 
[root@node23 ~]# cat -An a_file 
     1  Line #1$
     2  Line #2$
     3  xxx inserted line xxx$
     4  Line #3$
     5  Line #4$
     6  Line #5$
     7  Line #6$
     8  Line #7$
     9  Line #8$
    10  Line #9$
    11  Line #10$
[root@node23 ~]# 
[root@node23 ~]# sed -e '5ixxx (inserted) "line" xxx' -i a_file
[root@node23 ~]# cat -n a_file 
     1  Line #1
     2  Line #2
     3  xxx inserted line xxx
     4  Line #3
     5  xxx (inserted) "line" xxx
     6  Line #4
     7  Line #5
     8  Line #6
     9  Line #7
    10  Line #8
    11  Line #9
    12  Line #10
[root@node23 ~]# 

¿De dónde viene el final $de la línea 3 después de la inserción?
jww

Es de -Abandera a cat:)
jno

¿Qué pasa si la cadena que desea insertar contiene comillas, paréntesis, etc.?
Anentropic

Ver actualización del texto anterior. Eso significa que tendrá que escapar de esos caracteres según corresponda.
junio

0

sed -i "" -e $ '4 a \\ n''Project_Name = sowstest' start

  • Esta línea funciona bien en macOS
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.