bash - sustituir - sed reemplazar linea completa
Cómo reemplazar una línea completa en un archivo de texto por número de línea (8)
Dado este archivo de prueba (test.txt)
Lorem ipsum dolor sit amet,
consectetur adipiscing elit.
Duis eu diam non tortor laoreet
bibendum vitae et tellus.
el siguiente comando reemplazará la primera línea por "texto de nueva línea"
$ sed ''1 c/
> newline text'' test.txt
Resultado:
newline text
consectetur adipiscing elit.
Duis eu diam non tortor laoreet
bibendum vitae et tellus.
más información se puede encontrar aquí
http://www.thegeekstuff.com/2009/11/unix-sed-tutorial-append-insert-replace-and-count-file-lines/
Tengo una situación en la que quiero un script bash para reemplazar una línea completa en un archivo. El número de línea siempre es el mismo, por lo que puede ser una variable codificada.
No estoy tratando de reemplazar una subcadena en esa línea, solo quiero reemplazar esa línea por completo con una nueva línea.
¿Hay algún método bash para hacer esto (o algo simple que pueda ser lanzado en un script .sh)?
De hecho, utilicé esta secuencia de comandos para reemplazar una línea de código en el archivo cron en los servidores UNIX de nuestra empresa hace un tiempo. Lo ejecutamos como script de shell normal y no tuvimos problemas:
#Create temporary file with new line in place
cat /dir/file | sed -e "s/the_original_line/the_new_line/" > /dir/temp_file
#Copy the new file over the original file
mv /dir/temp_file /dir/file
Esto no va por número de línea, pero puede cambiar fácilmente a un sistema basado en el número de línea colocando el número de línea antes de la s/
y colocando un comodín en lugar de la the_original_line
.
Excelente respuesta de Chepner. Me está funcionando en bash Shell.
# To update/replace the new line string value with the exiting line of the file
MyFile=/tmp/ps_checkdb.flag
`sed -i "${index}s/.*/${newLine}/" $MyFile`
aquí
index
- Línea no
newLine
- nueva cadena de líneas que queremos reemplazar.
De manera similar, debajo del código se usa para leer una línea particular en el archivo. Esto no afectará el archivo real.
LineString=`sed "$index!d" $MyFile`
aquí
!d
- eliminará las líneas que no sean la línea no $index
Por lo tanto, obtendremos el resultado como una cadena de línea de ningún $index
en el archivo.
Incluso puede pasar parámetros al comando sed:
test.sh
#!/bin/bash
echo "-> start"
for i in $(seq 5); do
# passing parameters to sed
j=$(($i+3))
sed -i "${j}s/.*/replaced by ''$i''!/" output.dat
done
echo "-> finished"
exit
orignial output.dat:
a
b
c
d
e
f
g
h
i
j
Ejecutando ./test.sh da el nuevo output.dat
a
b
c
replaced by ''1''!
replaced by ''2''!
replaced by ''3''!
replaced by ''4''!
replaced by ''5''!
i
j
No es el mejor, pero esto debería funcionar:
sed -i ''Ns/.*/replacement-line/'' file.txt
donde N
debe ser reemplazado por su número de línea objetivo. Esto reemplaza la línea en el archivo original. Para guardar el texto modificado en un archivo diferente, descarte la opción -i
:
sed ''Ns/.*/replacement-line/'' file.txt > new_file.txt
Supongamos que desea reemplazar la línea 4 con el texto "diferente". Puede usar AWK como ese:
awk ''{ if (NR == 4) print "different"; else print $0}'' input_file.txt > output_file.txt
AWK considera que la entrada es "registros" divididos en "campos". Por defecto, una línea es un registro. NR
es la cantidad de registros vistos. $0
representa el registro completo actual (mientras que $1
es el primer campo del registro y así sucesivamente, de manera predeterminada los campos son palabras de la línea).
Entonces, si el número de línea actual es 4, imprima la cadena "diferente" pero imprima la línea sin cambios.
En AWK, el código del programa encerrado en { }
ejecuta una vez en cada registro de entrada.
Debe citar el programa AWK entre comillas simples para evitar que la consola intente interpretar cosas como $0
.
EDITAR: Un programa AWK más corto y más elegante de @chepner en los comentarios a continuación:
awk ''NR==4 {$0="different"} { print }'' input_file.txt
Solo para el registro (es decir, la línea) número 4, reemplace el registro completo con la cadena "diferente". Luego, para cada registro de entrada, imprima el registro.
¡Claramente mis habilidades AWK están oxidadas! Gracias, @chepner.
EDITAR: y ver también una versión aún más corta de @Dennis Williamson:
awk ''NR==4 {$0="different"} 1'' input_file.txt
Cómo funciona esto se explica en los comentarios: el 1
siempre evalúa verdadero, por lo que el bloque de código asociado siempre se ejecuta. Pero no hay un bloque de código asociado, lo que significa que AWK realiza su acción predeterminada de solo imprimir toda la línea. AWK está diseñado para permitir programas sencillos como este.
en bash, reemplace N, M por los números de línea y xxx yyy por lo que quiera
i=1
while read line;do
if((i==N));then
echo ''xxx''
elif((i==M));then
echo ''yyy''
else
echo "$line"
fi
((i++))
done < orig-file > new-file
EDITAR
De hecho, en esta solución hay algunos problemas, con los caracteres "/ 0" "/ t" y "/"
"/ t", se puede resolver poniendo IFS = antes de leer: "/", al final de la línea con -r
IFS= read -r line
pero para "/ 0", la variable está truncada, no hay una solución en pure bash: Asigna cadena que contiene null-character (/ 0) a una variable en Bash Pero en el archivo de texto normal no hay nul character / 0
perl sería una mejor opción
perl -ne ''if($.==N){print"xxx/n"}elsif($.==M){print"yyy/n"}else{print}'' < orig-file > new-file
# Replace the line of the given line number with the given replacement in the given file.
function replace-line-in-file() {
local file="$1"
local line_num="$2"
local replacement="$3"
# Escape backslash, forward slash and ampersand for use as a sed replacement.
replacement_escaped=$( echo "$replacement" | sed -e ''s/[//&]///&/g'' )
sed -i "${line_num}s/.*/$replacement_escaped/" "$file"
}