Dodanie wiersza tekstu do wielu plików

10

Mam więc kilka plików w katalogu i muszę wstawić wiersz tekstu do każdego z nich. Mają zasadniczo następujący format:


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

I chciałbym wstawić linię przed zamknięciem

</VirtualHost>
etykietka. Moje pierwsze założenie jest takie, że powinienem być w stanie to zrobić przy pomocy sed, prawdopodobnie dopasowując i zastępując ten tag. Zacznę teraz próbować tego, ale jeśli ktoś ma taki sposób, chciałbym to usłyszeć.

Gabe.
źródło
Będę szczery, gdy powiem, że myślę, że to bardziej zadanie programistyczne ... i dlatego powinno być na SO. Użyłbym do tego Perla, zwłaszcza, że ​​założę się, że istnieje moduł Perla zaprojektowany do analizowania i modyfikowania konfiguracji apache.
ksenoterrakid
2
Dzięki, ale jest to zadanie, które powinno być łatwe do zrealizowania za pomocą prostych narzędzi uniksowych, dlatego zapytałem tutaj. Ale dziękuję za twój komentarz.
Gabe.

Odpowiedzi:

10

Coś takiego:

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

Pracuje. Jeśli chcesz powtórzyć to polecenie na wielu plikach, możesz zrobić coś takiego:

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

Prawdopodobnie lepszy (ale nie przetestowany) dzięki @ChrisDown:

find . -type f -print0 | while IFS= read -r -d '' filename;\
do sed -i 's/<\/VirtualHost>/yourlinehere\n<\/VirtualHost>/' $filename;\ 
done
lcipriani
źródło
super ... właśnie tego szukałem.
Gabe.
1
Czy nie analizować ls. Zamiast tego użyj globu. mywiki.wooledge.org/ParsingLs
Chris Down
Jesteś rygorystyczny @ChrisDown. Popraw moją odpowiedź.
lcipriani
Wybór innej postaci niż /wyrażenie sed jest czystszy, ponieważ nie musisz uciekać przed ukośnikiem:'s:</VirtualHost>:yourlinehere\n</VirtualHost>:'
Alexander
2

Jeśli nie masz nic przeciwko Perlowi, spróbuj:

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

-iPrzełącznik zbawi swój stary plik z .oldrozszerzeniem i wydrukować do obecnego.

gvkv
źródło
2

Możesz także użyć „ex” (linia poleceń vi), jeśli edycja, którą chcesz wykonać, jest nawet nieco skomplikowana. Na przykład chcesz wstawić tylko dla jednego wystąpienia „”.

Taki skrypt powłoki może działać:

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

Takie podejście daje zalety „ex”: znalezienie lokalizacji z wzorami elaboarte i „ruchy kursora”. Możesz zrobić takie rzeczy, jak znaleźć wzór, a następnie znaleźć następną instancję, TO następnie wstawić. Lub możesz zmienić tekst, a nie tylko wstawiać. Lub możesz zmieniać zakresy. Nie zapominaj, że „ex” pozwala używać ”. jako bieżąca linia, więc. / ^ somepatter / s / blah / foo / będzie działać.

Bruce Ediger
źródło
0

Możesz użyć następującego kodu pojedynczej linii, aby wstawić jedną linię lub wiele linii do danej lokalizacji w pliku, w twoim przypadku przed „VirtualHost”. Kod w zasadzie wyszukuje nazwę pliku (może to być *. *, Jeśli chcesz wstawić teksty do wszystkich plików) w danym katalogu i jego podkatalogach. W obrębie znalezionych plików szuka wzorca „VirtualHost”. Po znalezieniu wzorca zastępuje go wierszem pierwszym \ nsecondline \ notherlines \ n \ VirtualHost. Pamiętaj, że „VirtualHost” jest częścią tekstu do wymiany, w przeciwnym razie go utracimy.

find directory/ -name filename -print | xargs sed -i 's|VirtualHost|firstline\nsecondline\notherlines\nVirtualHost|g'
Oufie
źródło