lineas - sed reemplazar/
Inserta una línea en el número de línea específico con sed o awk (8)
Tengo un archivo de script que necesito modificar con otra secuencia de comandos para insertar un texto en la octava línea.
Cadena para insertar: Project_Name=sowstest
, en un archivo llamado start
.
Traté de usar awk y sed, pero mi comando se confunde.
OS X / macOS sed
El -i
funciona de forma diferente en macOS sed
que en GNU sed
.
Esta es la manera de usarlo en macOS / OS X:
sed -i '''' ''8i/
8 This is Line 8'' FILE
Ver man 1 sed
para más información.
POSIX sed
(y, por ejemplo, el sed
OS X, el sed
continuación) requieren que i
sea seguido por una barra invertida y una nueva línea. Además, al menos, sed
OS X no 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
awk
interpreta barras invertidas en variables pasadas con -v
pero no en 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
Tanto ENVIRON
como -v
están definidos por POSIX.
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 personaje de la línea.
- La segunda parte del comando debe estar en una segunda línea.
Soluciones de Perl:
rápido y sucio:
perl -lpe ''print "Project_Name=sowstest" if $. == 8'' file
-
-l
quita las nuevas líneas y las agrega nuevamente, eliminando la necesidad de "/ n" -
-p
bucles sobre 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, usando argumentos con nombre:
perl -slpe ''print $s if $. == $n'' -- -n=8 -s="Project_Name=sowstest" file
-
-s
permite un analizador de argumentos rudimentario -
--
previene que el analizador de argumentos perl estándar analice -n y -s
argumentos de comando de posición:
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 largas y largas
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
Una respuesta ed
ed file << END
8i
Project_Name=sowstest
.
w
q
END
.
en su propia línea finaliza el modo de entrada; w
escribe; q
GNU ed tiene un comando wq
para guardar y salir, pero los ed antiguos no.
Lectura adicional: https://gnu.org/software/ed/manual/ed_manual.html
la respuesta awk
awk -v n=8 -v s="Project_Name=sowstest" ''NR == n {print s} {print}'' file > file.new
sed -e ''8iProject_Name=sowstest'' -i start
usar GNU sed
Muestra de ejecución:
[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 ~]#
sed -i ''8i8 This is Line 8'' FILE
inserciones en la línea 8
8 This is Line 8
en archivo FILE
-i
hace la modificación directamente al archivo FILE, sin salida a stdout, como se menciona en los comentarios de glenn jackman.