Por alguna razón, parece que no puedo encontrar una respuesta directa a esto y en este momento estoy un poco apretado. ¿Cómo haré para insertar una línea de texto de elección después de que la primera línea coincida con una cadena específica usando el sed
comando? Yo tengo ...
CLIENTSCRIPT="foo"
CLIENTFILE="bar"
Y quiero insertar una línea después de la CLIENTSCRIPT=
línea que resulta en ...
CLIENTSCRIPT="foo"
CLIENTSCRIPT2="hello"
CLIENTFILE="bar"
sed
. Esa no es lased
sintaxis estándar y no funcionará con ninguna otrased
implementación.Tenga en cuenta la
sed
sintaxis estándar (como en POSIX, compatible con todas lassed
implementaciones conformes (GNU, OS / X, BSD, Solaris ...)):O en una línea:
(
-e
xpressions (y el contenido de-f
iles) se unen con nuevas líneas para formar lassed
interpretaciones del script sed ).La
-i
opción para la edición en el lugar también es una extensión de GNU, algunas otras implementaciones (como FreeBSD) son compatibles-i ''
con eso.Alternativamente, para la portabilidad, puede usar
perl
en su lugar:O podrías usar
ed
oex
:fuente
sed -e '/CLIENTSCRIPT=/a\' -e 'CLIENTSCRIPT2="hello"' file
escapa a la cita al final del primer parámetro y rompe el comando.csh
orc
familia,'...'
son citas fuertes dentro de las cuales la barra invertida no es especial. La única excepción que sé es elfish
shell.sed
no cumple con POSIX aquí. Eso hace que mi declaración sobre que sea portátil sea incorrecta (para la variante de una línea). Le pediré confirmación al opengroup si realmente es una no conformidad o una mala interpretación del estándar de mi parte.Una POSIX compatible con el
s
comando:fuente
sed -e '/.../s/$/\' -e 'CLI.../'
qué evitaría problemas con líneas que contienen secuencias de bytes que no forman caracteres válidos.Comando Sed que funciona en MacOS (al menos, OS 10) y Unix por igual (es decir, no requiere gnu sed como lo hace Gilles (actualmente aceptado)):
Esto funciona en bash y quizás 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 antiguos / POSIX sed. Si puede haber varias líneas que coincidan con CLIENTSCRIPT = "foo" (o su equivalente) y solo desea agregar la línea adicional la primera vez, puede volver a trabajarla de la siguiente manera:
(esto crea un bucle después del código de inserción de línea que simplemente pasa por el resto del archivo, sin volver nunca más al primer comando sed).
Puede notar que agregué un '^ *' al patrón coincidente en caso de que la línea aparezca en un comentario, digamos o esté sangrada. No es 100% perfecto, pero cubre algunas otras situaciones que probablemente sean comunes. Ajuste según sea necesario ...
Estas dos soluciones también resuelven el problema (para la solución genérica para agregar una línea) de que si su nueva línea insertada contiene barras invertidas o símbolos sin escape, serán interpretados por sed y probablemente no saldrán de la misma manera, tal como
\n
es, por ejemplo.\0
Sería la primera línea coincidente. Especialmente útil si está agregando una línea que proviene de una variable donde de lo contrario tendría que escapar de todo primero usando $ {var //} antes, u otra declaración sed, etc.Esta solución es un poco menos desordenada en los scripts (sin embargo, citar y \ n no es fácil de leer), cuando no desea colocar el texto de reemplazo para un comando al comienzo de una línea, por ejemplo, en una función Con líneas dentadas. Aproveché que $ '\ n' es evaluado a una nueva línea por el shell, no está en valores regulares '\ n' entre comillas simples.
Se está haciendo lo suficientemente largo, aunque creo que perl / incluso awk podría ganar debido a que es más legible.
fuente
s/CLIENTSCRIPT="foo"/&\
[Entrar]CLIENTSCRIPT2="hello"/
. La barra diagonal inversa debe ser el último carácter de la línea (sin espacios en blanco después), al contrario de cómo se ve en este comentario.s///
, así como las de los comandosa
yi
se pueden "escapar", utilizando el mismo método que describo en mi comentario anterior.Tal vez sea un poco tarde para publicar una respuesta para esto, pero encontré algunas de las soluciones anteriores un poco engorrosas.
Intenté el reemplazo simple de cadenas en sed y funcionó:
El signo & refleja la cadena coincidente, y luego agrega \ ny la nueva línea.
Como se mencionó, si desea hacerlo en el lugar:
Otra cosa. Puedes unir usando una expresión:
Espero que esto ayude a alguien
fuente
\n
la cadena de reemplazo. Llano-vainilla (POSIX)sed
no no entiende\n
en la cadena de reemplazo, sin embargo, por lo que este no funcionará en BSD o MacOS, a menos que haya instalado GNU sed de alguna manera. Con vanilla sed puede incrustar nuevas líneas "escapando" de ellas, es decir, terminando la línea con una barra diagonal inversa, luego presionando [Enter] ( referencia , debajo del encabezado para[2addr]s/BRE/replacement/flags
). Esto significa que su comando sed tiene que abarcar varias líneas en la terminal.La variante awk:
fuente
1;
, vea ¿Por qué "1" en awk imprime la línea actual?Tuve una tarea similar y no pude hacer funcionar la solución perl anterior.
Aquí está mi solución:
perl -i -pe "BEGIN{undef $/;} s/^\[mysqld\]$/[mysqld]\n\ncollation-server = utf8_unicode_ci\n/sgm" /etc/mysql/my.cnf
Explicación:
Utiliza una expresión regular para buscar una línea en mi archivo /etc/mysql/my.cnf que solo contenía
[mysqld]
y lo reemplazó por[mysqld] collation-server = utf8_unicode_ci
agregando efectivamente la
collation-server = utf8_unicode_ci
línea después de la línea que contiene[mysqld]
.fuente
Tuve que hacer esto recientemente también para Mac y Linux OS y después de navegar por muchas publicaciones y probar muchas cosas, en mi opinión particular, nunca llegué a donde quería, que es: una solución lo suficientemente simple como para comprender usando y comandos estándar con patrones simples, un revestimiento, portátil, expandible para agregar más restricciones. Luego traté de mirarlo con una perspectiva diferente, fue entonces cuando me di cuenta de que podía prescindir de la opción "un trazador de líneas" si un "trazador de líneas 2" cumplía con el resto de mis criterios. Al final se me ocurrió esta solución, me gusta, funciona tanto en Ubuntu como en Mac, que quería compartir con todos:
En el primer comando, grep busca números de línea que contengan "foo", cut / head selecciona la primera aparición, y la operación aritmética incrementa ese primer número de línea de aparición en 1 ya que quiero insertar después de la aparición. En el segundo comando, es una edición de archivo en el lugar, "i" para insertar: una nueva línea que cita ansi-c, "barra", luego otra nueva línea. El resultado es agregar una nueva línea que contiene "barra" después de la línea "foo". Cada uno de estos 2 comandos se puede ampliar a operaciones más complejas y coincidencia.
fuente