Estoy tratando de cambiar una sola palabra en una línea específica en un archivo, pero tengo algunos problemas para conectarlos todos juntos.
Básicamente, en una línea de mi archivo hay una palabra clave 'firmware_revision', y en esta línea (y solo en esta línea) quiero reemplazar la palabra 'prueba' con la palabra 'producción'.
Entonces puedo hacer esto:
grep 'firmware_revision' myfile.py | sed 's/test/production'
Esto seleccionará la línea que deseo y realizará la sustitución, pero no puedo encontrar la manera de colocar esta nueva línea en el archivo original para reemplazar la línea anterior. Obviamente no puedo simplemente redirigirlo de nuevo al archivo, entonces, ¿qué debo hacer?
Incluso si uso temporarios, al usar grep
para obtener solo la línea que necesito, pierdo todos los demás datos en el archivo, por lo que ya no puedo redirigir todo a un archivo temporal y luego reemplazar el original con la temperatura.
Editar: alguien solicitó más información
Digamos que tengo un archivo lleno de líneas como esta
[
('key_name1', str, 'value1', 'Description'),
('key_name2', str, 'value2', 'Description'),
('key_name3', str, 'value3', 'Description'),
('firmware_revision', str, 'my-firmware-name-test', 'Firmware revision name')
]
ahora quiero escribir un script (idealmente de una línea) que encontrará la línea que contiene 'firmware_revision', y cambia todas las instancias de la palabra 'prueba' en esa línea a 'producción'. La palabra 'prueba' podría estar en otros lugares en ese archivo y no quiero que se cambien. Para que quede claro, quiero cambiar la línea anterior a
('firmware_revision', str, 'my-firmware-name-production', 'Firmware revision name')
¿Cómo hago esto?
fuente
sed
es muy potente, puede realizar ambas funciones (grep
y sustitución) pero necesitaremos más información sobre cómo se ve la línea para ayudarlo.sed -i.bak '/firmware_revision/ s/test/production/' myfile.py
Respuestas:
Tratar:
Aquí,
/firmware_revision/
actúa como una condición. Es cierto para las líneas que coinciden con la expresión regularfirmware_revision
y falso para otras líneas. Si la condición es verdadera, se ejecuta el siguiente comando. En este caso, ese comando es un comando sustituto que reemplaza la primera aparición detest
conproduction
.En otras palabras, el comando
s/test/production/
se ejecuta solo en líneas que coinciden con la expresión regularfirmware_revision
. Todas las demás líneas pasan sin cambios.Por defecto, sed envía su salida a la salida estándar. Sin embargo, usted quería cambiar el archivo en su lugar. Entonces, agregamos la
-i
opción. En particular,-i.bak
hace que el archivo se cambie en su lugar con una copia de seguridad guardada con una.bak
extensión.Si ha decidido que el comando funciona para usted y desea vivir peligrosamente y no crear una copia de seguridad, entonces, con GNU sed (Linux), use:
Por el contrario, en BSD (OSX), la
-i
opción debe tener un argumento. Si no desea mantener una copia de seguridad, proporcione un argumento vacío. Por lo tanto, use:Editar
En la edición de la pregunta, el OP pide que se sustituya cada aparición
test
en la líneaproduction
. En ese caso, agregamos lag
opción al comando sustituto para un reemplazo global (para esa línea):fuente
-i.bak
parte también.-i
agregado.sed
pueden hacer ...''
después-i
?sed -i '/firmware_revision/ s/test/production/g' myfile.py
contrario, solo se cambia la primera instancia.En máquinas más antiguas con la vieja escuela
sed
que no admite la opción-i
:fuente
ed
y hacerlo en una línea:printf %s\\n g/firmware_revision/s/test/production/g w q | ed -s myfile.py
ed(1)
no ofrece ningún pretexto para mostrar el uso demktemp(1)
.ed
hace. En lugar demv -f "$TF" myfile.pl
usarcat "$TF" > myfile.pl && rm -f "$TF"
. Por cierto, es una buena práctica usar nombres de variables en minúsculas (en$tf
lugar de$TF
), se garantiza que no entren en conflicto con ningún vars incorporado en bash (probablemente también otros shells bourne).cat "$TF" > myfile.pl
prueba esto:touch a b; chmod 0444 a; cat b >a
(Por cierto,sed -i
tampoco funcionará en ese caso). Mejor deje que el usuario se ocupe de eso. Re::rm -f "$TF"
no es necesario, vertrap ... EXIT
. Re: en$tf
lugar de$TF
: tal vez; Es una cuestión de estilo.umask
difiere de los permisos originales. En cuanto a los mayúsculas, no es solo una cuestión de estilo: muchas personas que han cometido el error de usar mayúsculas PATH o RANDOM o SHELL o lo que sea para sus propias variables lo han descubierto de la manera difícil. (y sí, a menudo uso mayúsculas también. Sé que está mal, estoy tratando de romper el hábito).