NFsec Logo

Wyszukiwanie i zastępowanie z Perlem

07/08/2009 w Hacks & Scripts Brak komentarzy.  (artykuł nr 119, ilość słów: 613)

P

rzedstawiony hack jest tłumaczeniem „Global Search and Replace with Perl” z książki „Linux Servers Hacks” autorstwa Rob’a Flickenger’a udostępnionym on-line (Hack #73) na stronie http://hacks.oreilly.com. Do tłumaczenia zostało dodane także parę informacji od tłumacza.

   Istnieje grupa parametrów, które czynią język Perl bardzo przydatnym narzędziem do edycji linii poleceń. Naucz się tych parametrów, i Ty wtedy dowiesz się jak wymruknąć magiczne, jednowierszowe skrypty Perla by pogmatwać plany przyjaciół (i wystraszyć twojego szefa projektu).

Pierwszym z nich jest -e. Daj Perlowi -e, a za nim wiersz kodu i uruchomi się jak zwykły skrypt Perl:

rob@catlin:~$ perl -e 'print "Hi, Ma!\n"'
Hi, Ma!

Zapamiętaj sobie, że kończący znak ; nie jest potrzebny w jednoliniowcach. Generalnie dobrze jest umieścić twoją linię w pojedynczych cudzysłowach, aby zapobiec interpretowania przez powłokę znaków specjalnych (takich jak ! oraz \ powyżej).

Następny parametr jest trochę bardziej skomplikowany, ale stanie się twoją drugą naturą od kiedy zaczniesz go używać: -p. Z dokumentacji perldoc perlrun:

-p powoduje, że Perl uznaje następującą pętle w twoim programie,
która powoduje iterację po argumentach nazw plików po trochu jak sed:

LINE:
while (<>) {
... # twoj program idzie tutaj
} continue {
print or die "-p przeznaczenie: $!\n";
}

Linia w wierszu ($_) jest automatycznie wyświetlana w każdej interracji pętli. Jeśli połączysz kombinację parametrów -p i -e, otrzymasz jednowierszowy skrypt iterujący po każdym pliku w wierszu poleceń lub następującym po nim tekście podanym do niego przez STDIN. Dla przykładu skomplikowane polecenie cat:

rob@catlin:~$ perl -pe 1 /etc/hosts
#
# hosts This file describes a number of hostname-to-address
# mappings for the TCP/IP subsystem.
#

# For loopbacking.
127.0.0.1 localhost

Jedynka (1) to po prostu kod powrotu (jeśli wprowadziłeś 1; w skrypcie Perla, która jest równoważna: return 1;). Ponieważ wiersze są drukowane automatycznie, program określony parametrem -e nie musi robić nic więcej.

Momentem, w którym robi się ciekawie jest podawanie kodu manipulującego aktualnym wierszem przed jego wyświetleniem. Dla przykładu, załóżmy, że chcesz dołączyć nazwę lokalnej maszyny do wiersza localhost:

rob@catlin:~$ perl -pe 's/localhost/localhost $ENV{HOSTNAME}/' /etc/hosts
#
# hosts This file describes a number of hostname-to-address
# mappings for the TCP/IP subsystem.
#

# For loopbacking.
127.0.0.1 localhost catlin.nocat.net

lub może chciałbyś zmienić twoje ustawienia daemona inetd:

rob@caligula:~$ perl -pe 's/^(\s+)?(telnet|shell|login|exec)/# $2/' \
\  /etc/inetd.conf

Wyświetli to zawartość pliku /etc/inetd.conf na STDOUT, umieszczając w komentarzach wszystkie nie zakomentowane wiersze telnet, shell, login lub exec po drodze. Naturalnie, możemy to przekierować z powrotem do pliku, ale jeśli chcemy tylko poddać edycji plik, istnieje lepszy sposób: parametr -i.

-i pozwala na edycję plików w miejscu. A więc, aby zakomentować wszystkie powyższe linie w /etc/inetd.conf, możesz spróbować:

root@catlin:~# perl -pi -e 's/^(\s+)?(telnet|shell|login|exec)/# $2/' \
/etc/inetd.conf

lub nawet lepiej:

root@catlin:~# perl -pi.orig -e 's/^(\s+)?(telnet|shell|login|exec)/# $2/' \
/etc/inetd.conf

Drugi przykład powoduje utworzenie kopii zapasowej pliku /etc/inetd.conf w pliku /etc/inetd.conf.orig przed zmianą oryginału. Nie zapomnij przesłać sygnału HUP do daemona inetd, w celu uwzględnienia zmian.

Tak samo łatwa jest edycja wielu plików w miejscu, w tym samym czasie. Możesz podać każdą liczbę plików (lub dzikich kart / symboli wieloznacznych) w wierszu poleceń:

rob@catlin:~$ perl -pi.bak -e 's/bgcolor=#ffffff/bgcolor=#000000/i' *.html

To polecenie spowoduje zmianę koloru tła wszystkich stron html w bieżącym z białego koloru na czarny. Nie zapomnij o końcowym znaku i, dzięki któremu wzorzec jest rozpoznawany bez względu na wystąpienie wielkich i małych liter (tak samo traktuje się bgcolor=#FFFFFF i BGColor=#FfFffF).

A, co jeśli jesteś w trakcie pracy nad projektem CVS i potrzebujesz zmienić serwer CVS, na którym zatwierdasz poprawki? Proste, jeśli skierujesz potokiem wyjście polecenia find poprzez polecenie xargs uruchamiając polecenie: perl -pi e:

schuyler@ganesh:~/nocat$ find -name Root | xargs perl -pi -e \
's/cvs.oldserver.com/cvs.newserver.org/g'

Następnie zresetuj zmienną $CSVROOT i normalnie wyrejestruj plik z repozytorium CVS. Projekt zostanie potem automatycznie zarejestrowany w cvs.newserver.org.

Perl w wierszu poleceń może posłużyć do wykonania bardzo skomplikowanych operacji przekształceń. Naucz się wyrażeń regularnych i korzystaj z nich mądrze. W ten sposób unikniesz tysięcy niepotrzebnych edycji ręcznych.

Więcej informacji: Perl, man perldoc, perlrun, Hacks O’Reilly

Kategorie K a t e g o r i e : Hacks & Scripts

Tagi T a g i : , , , ,

Zostaw odpowiedź.

Musisz być zalogowany by móc komentować.