Agregar una línea de texto a múltiples archivos

10

Entonces, tengo un montón de archivos en un directorio, y necesito insertar una línea de texto en cada uno de ellos. Tienen esencialmente el siguiente formato:


<VirtualHost *:80>
        ServerAdmin gabe@localhost
        DocumentRoot /var/www/test1
        ServerName test1.local
        ServerAlias test1
        <Directory "/var/www/test1">
                Options All
                AllowOverride All
        </Directory>
</VirtualHost>

Y me gustaría insertar una línea antes del cierre

</VirtualHost>
etiqueta. Mi primera suposición es que debería poder hacer esto con sed, probablemente haciendo coincidir y reemplazando esa etiqueta. Voy a comenzar a intentar esto ahora, pero si alguien tiene una forma existente de hacerlo, me encantaría escucharlo.

gabe
fuente
Seré honesto cuando digo que creo que esto es más una tarea de programación ... y por lo tanto debería estar en SO. Usaría Perl para hacerlo, especialmente porque apuesto a que hay un módulo perl diseñado para analizar y modificar configuraciones de apache.
xenoterracide
2
Gracias, pero es una tarea que debería ser fácil de realizar con herramientas simples de Unix, por lo tanto, se pregunta aquí. Gracias por tu comentario, sin embargo.
Gabe.

Respuestas:

10

Algo como esto:

sed 's/<\/VirtualHost>/yourlinehere\n<\/VirtualHost>/'

trabajos. Si desea repetir este comando en muchos archivos, puede hacer algo como:

for i in *; do sed -i 's/<\/VirtualHost>/yourlinehere\n<\/VirtualHost>/' "$i"; done

Probablemente mejor (pero no probado) gracias a @ChrisDown:

find . -type f -print0 | while IFS= read -r -d '' filename;\
do sed -i 's/<\/VirtualHost>/yourlinehere\n<\/VirtualHost>/' $filename;\ 
done
lcipriani
fuente
increíble ... esto es justo lo que estaba buscando.
Gabe.
1
No , no analizar ls. Use un globo en su lugar. mywiki.wooledge.org/ParsingLs
Chris Down
Eres justo @ChrisDown. Por favor, mejora mi respuesta.
lcipriani
Elegir un carácter diferente al /de la expresión sed es más limpio, ya que no tiene que escapar de la barra:'s:</VirtualHost>:yourlinehere\n</VirtualHost>:'
Alexander
2

Si no te importa Perl prueba:

perl -pi'*.old' -e 's(</VirtualHost>(Your stuff here\n</VirtualHost>)' myfile

El -iinterruptor guardará su archivo anterior con una .oldextensión e imprimirá al actual.

gvkv
fuente
2

También puede usar "ex" (línea de comando vi) si la edición que desea hacer es incluso algo complicada. Por ejemplo, solo desea realizar la inserción en una instancia de "".

Un script de shell como este puede funcionar:

for FILENAME in *.whatever  # Need a criteria to glob, or a list of names
do
    ex -s $FILENAME << END_EDITS
/^<\/VirtualHost>/
O " capital-o, not zero
text to insert goes here
.
w!
q
END_EDITS
done

Este enfoque le brinda las ventajas de "ex": encontrar una ubicación con patrones elaborados y 'movimientos del cursor'. Puede hacer cosas como buscar un patrón, luego buscar la siguiente instancia, LUEGO hacer la inserción. O puede cambiar el texto, en lugar de simplemente insertar. O puede cambiar entre rangos. No olvides que "ex" te permite usar "." como la línea actual, entonces, / ^ somepatter / s / blah / foo / funcionará.

Bruce Ediger
fuente
0

Puede usar el siguiente código de línea única para insertar una sola línea o varias líneas en una ubicación determinada en un archivo, en su caso antes de 'VirtualHost'. El código básicamente busca el nombre de archivo (podría ser *. *, Si desea insertar los textos en todos los archivos) dentro del directorio dado y sus subdirectorios. Dentro de los archivos encontrados, busca el patrón 'VirtualHost'. Después de encontrar el patrón, lo reemplaza con firstline \ nsecondline \ notherlines \ n \ VirtualHost. Tenga en cuenta que 'VirtualHost' es parte del texto para el reemplazo, de lo contrario lo perderemos.

find directory/ -name filename -print | xargs sed -i 's|VirtualHost|firstline\nsecondline\notherlines\nVirtualHost|g'
Oufie
fuente