Co każdy haker Perla powinien wiedzieć o perl-ne?
Używam wiersza poleceń Perla z opcją -ne
od lat, głównie do przetwarzania plików tekstowych w sposób, w jaki sed nie może. Przykład:
cat in.txt | perl -ne "s/abc/def/; s/fgh/hij/; print;" > out.txt
Nie mam pojęcia, gdzie się tego nauczyłem i dopiero dziś przeczytałem perlrun i znalazłem Inne formy (perl -pe
na przykład).
Co jeszcze powinienem wiedzieć o perl -ne
?
7 answers
perl -ne 'CODE'
jest odpowiednikiem programu
while (<>) {
CODE
}
perl -ane 'CODE'
i perl -F/PATTERN/ -ane
są również dobrymi idiomami, o których warto wiedzieć. Są równoważne
while (<>) {
@F = split /\s+/, $_;
CODE
}
I
while (<>) {
@F = split /PATTERN/, $_;
CODE
}
Przykład: zaawansowany grep :
perl -ne 'print if/REGEX1/&&!/REGEX2/&&(/REGEX3/||/REGEX4/&&!/REGEX5/)' input
perl -F/,/ -ane 'print if $F[2]==4&&$F[3]ge"2009-07-01"&&$F[3]lt"2009-08-01"' file.csv
Szczególnie sprytnym przykładem, który używa niedopasowanych szelek jest tutaj .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:14
Jest jedna ważna rzecz, którą należy wiedzieć o skryptach perl -ne
i perl -pe
: domyślnie używają <>
.
"dlaczego to jest ważne?"możesz zapytać.
Magiczny operator <>
używa 2 arg Formy Otwartej. Jeśli pamiętasz, 2 ARG open zawiera specyfikację mode z nazwą pliku w jednym argumencie. Wywołanie w starym stylu {[4] } jest podatne na manipulację trybem plików. Szczególnie interesującym trybem w tym kontekście jest |
-- otwierasz uchwyt do rury do procesu wykonujesz egzekucję.
Możesz myśleć " wielka sprawa!", ale jest.
- wyobraź sobie zadanie crona wykonywane przez roota do plików dziennika munge w jakimś katalogu.
- skrypt jest wywoływany jako
script *
. - wyobraź sobie plik w katalogu o nazwie
|rm -rf /
.
- powłoka rozszerza
*
i otrzymujemyscript file_1 file_2 '|rm -rf /' file_4
- skrypt przetwarza
file_1
ifile_2
. - następnie otwiera uchwyt na STDIN z
rm -rf /
. - dużo aktywność dysku następuje.
-
file_4
już nie istnieje, więc nie możemy go otworzyć.
Możesz przeczytać więcej dyskusji na ten temat na Perlmonks .
Morał historii: uważaj na operatora <>
.
FWIW, właśnie potwierdziłem, że nadal jest to problem z perlem 5.10.0.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-07 06:37:38
Możesz podać więcej niż jedną klauzulę-E. Czasami mam wiersz poleceń, który zaczyna rosnąć, gdy udoskonalam operację wyszukiwania / wyodrębniania / mangulacji. jeśli coś pomylisz, otrzymasz "numer linii" informujący, które -e ma błąd.
Oczywiście niektórzy mogą twierdzić, że jeśli masz więcej niż jedną lub dwie klauzule e, może powinieneś umieścić cokolwiek to jest w skrypcie, ale niektóre rzeczy naprawdę są po prostu wyrzucane, więc po co się trudzić.
perl -n -e 'if (/good/)' -e '{ system "echo $_ >> good.txt"; }' \
-e 'elsif (/bad/)' -e '{ system "echo $_ >> bad.txt"; }' \
-e 'else' -e '{ system "echo $_ >> ugly.txt"; }' in.txt another.txt etc.txt
Prawdopodobnie zrobiłbyś coś mniej trywialne niż grep / egrep w 3 plikach: -)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-06 08:07:04
Opcja -i
pozwala na wykonanie zmian w linii:
perl -i -pe 's/abc/def/; s/fgh/hij/' file.txt
Lub zapisz kopię zapasową:
perl -i.bak -pe 's/abc/def/; s/fgh/hij/' file.txt
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-06 11:43:41
Lubię myśleć o perl -n
jako o wybraniu konkretnych bitów wejścia i perl -p
jako map
dla wszystkich linii wejścia.
Jak zauważyliście, możliwe jest uzyskanie efektu -p
z -n
, a my możemy emulować na odwrót:
$ echo -e "1\n2\n3" | perl -pe '$_="" if $_ % 2 == 0' 1 3
Pomijanie linii z next
wydaje się bardziej naturalne, ale -p
owija kod w
LINE:
while (<>) {
... # your program goes here
} continue {
print or die "-p destination: $!\n";
}
Według projektu, next
Działa continue
bloki:
Jeśli istnieje
continue
blok, jest zawsze wykonywany tylko przed ponowną oceną warunku. W ten sposób można go wykorzystać do zwiększenia zmiennej pętli, nawet jeśli pętla jest kontynuowana za pomocą instrukcjinext
.
Przełącznik -l
ma dwa przydatne efekty:
- Z
-n
i-p
, automatyczniechomp
każdy rekord wejściowy. - Set
$\
więc każdyprint
domyślnie dodaje terminator.
/etc/services
, możesz
perl -ane 'print $F[1] if $F[1] =~ /udp/' /etc/services | head
Ale UPS:
7/udp9/udp11/udp13/udp17/udp19/udp37/udp39/udp42/ud...
Lepiej:
$ perl -lane 'print $F[1] if $F[1] =~ /udp/' /etc/services | head 7/udp 9/udp 11/udp 13/udp 17/udp 19/udp 37/udp 39/udp 42/udp 53/udp
Pamiętaj, że -n
i -p
mogą być również w linii shebang, więc aby zapisać Powyższy tekst jako skrypt:
#! /usr/bin/perl -lan
BEGIN {
@ARGV = ("/etc/services") unless @ARGV;
open STDOUT, "|-", "head" or die "$0: head failed";
}
print $F[1] if $F[1] =~ /udp/
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-06 13:22:00
Moja ulubiona Referencja do linerów Perl one (i top hit w Google za tę frazę) obejmuje perl -ne
: http://novosial.org/perl/one-liner/
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-13 02:30:57
Często używam sed
lub awk
ale bardzo podoba mi się Ta perl
pasująca funkcja pattern killer:
$ cat my-input.txt
git 111 HERE 2222 voila 333
any 444 HERE none start 555 HERE 6
svn 777 aaaa 8888 nothing
two 222 HERE 9999 HERE 0000
$ perl -nle 'print $a if (($a)=/HERE ([0-9]+)/)' my-input.txt
2222
6
9999
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-21 16:31:57