Ajout d'une ligne de texte à plusieurs fichiers

10

Donc, j'ai un tas de fichiers dans un répertoire et j'ai besoin d'insérer une ligne de texte dans chacun d'eux. Ils ont essentiellement le format suivant:


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

Et j'aimerais insérer une ligne avant la fermeture

</VirtualHost>
étiquette. Ma première hypothèse est que je devrais être capable de le faire avec sed, probablement en faisant correspondre et en remplaçant cette balise. Je vais commencer à essayer maintenant, mais si quelqu'un a un moyen de le faire, j'aimerais l'entendre.

gabe.
la source
Je serai honnête quand je dirai que je pense que c'est plus une tâche de programmation ... et devrait donc être sur SO. J'utiliserais Perl pour le faire, d'autant plus que je parie qu'il existe un module perl conçu pour analyser et modifier les configurations apache.
xenoterracide
2
Merci, mais c'est une tâche qui devrait être facile à accomplir avec de simples outils Unix, donc demandé ici. Merci pour votre commentaire.
gabe.

Réponses:

10

Quelque chose comme ça:

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

travaux. Si vous souhaitez répéter cette commande sur un grand nombre de fichiers, vous pouvez faire quelque chose comme:

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

Probablement mieux (mais non testé) grâce à @ChrisDown:

find . -type f -print0 | while IFS= read -r -d '' filename;\
do sed -i 's/<\/VirtualHost>/yourlinehere\n<\/VirtualHost>/' $filename;\ 
done
lcipriani
la source
génial ... c'est exactement ce que je cherchais.
gabe.
1
Ne pas analyser ls. Utilisez plutôt un glob. mywiki.wooledge.org/ParsingLs
Chris Down
Vous êtes rigth @ChrisDown. S'il vous plaît, améliorez ma réponse.
lcipriani
Choisir un caractère différent de celui /de l'expression sed est plus propre, car vous n'avez pas à échapper à la barre oblique:'s:</VirtualHost>:yourlinehere\n</VirtualHost>:'
Alexander
2

Si cela ne vous dérange pas, essayez Perl:

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

Le -icommutateur enregistrera votre ancien fichier avec une .oldextension et l'imprimera dans le fichier actuel.

gvkv
la source
2

Vous pouvez également utiliser "ex" (ligne de commande vi) si l'édition que vous souhaitez effectuer est même quelque peu compliquée. Par exemple, vous ne souhaitez effectuer l'insertion que sur une seule instance de "".

Un script shell comme celui-ci peut fonctionner:

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

Cette approche vous donne les avantages de "ex": trouver un emplacement avec des motifs elaboarte et des "mouvements de curseur". Vous pouvez faire des choses comme trouver un motif, puis trouver l'instance suivante, PUIS faire l'insertion. Ou vous pouvez changer le texte, plutôt que de simplement faire des insertions. Ou vous pouvez changer entre les gammes. N'oubliez pas que "ex" vous permet d'utiliser "." comme la ligne actuelle, donc., / ^ somepatter / s / blah / foo / fonctionnera.

Bruce Ediger
la source
0

Vous pouvez utiliser le code de ligne unique suivant pour insérer une seule ligne ou plusieurs lignes dans un emplacement donné dans un fichier, dans votre cas avant «VirtualHost». Le code recherche essentiellement le nom de fichier (il peut s'agir de *. *, Si vous souhaitez insérer les textes dans tous les fichiers) dans le répertoire donné et ses sous-répertoires. Dans les fichiers trouvés, il recherche le modèle «VirtualHost». Après avoir trouvé le modèle, il le remplace par firstline \ nsecondline \ notherlines \ n \ VirtualHost. Notez que «VirtualHost» fait partie du texte à remplacer, sinon nous le perdrons.

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