Я нахожу много острот Perl онлайн. Иногда я хочу преобразовать эти остроты в сценарий, потому что иначе я забуду синтаксис остроты.
Например, я использую следующую команду (из nagios.com):
tail -f /var/log/nagios/nagios.log | perl -pe 's/(\d+)/localtime($1)/e'
Я был бы для замены его чем-то вроде этого:
tail -f /var/log/nagios/nagios.log | ~/bin/nagiostime.pl
Однако я не могу выяснить лучший способ быстро бросить этот материал в сценарий. У кого-либо есть быстрый способ бросить эти остроты в сценарий Perl или Bash?
Вы можете преобразовать любое однострочное предложение Perl в полноценный сценарий, пропустив его через B::Deparse
бэкенд компилятора, который генерирует исходный код Perl:
perl -MO=Deparse -pe 's/(\d+)/localtime($1)/e'
outputs:
LINE: while (defined($_ = <ARGV>)) {
s/(\d+)/localtime($1);/e;
}
continue {
print $_;
}
Преимущество этого подхода перед расшифровкой флагов командной строки вручную заключается в том, что именно так Perl интерпретирует ваш сценарий, поэтому нет никаких догадок. B::Deparse
является модулем ядра, поэтому устанавливать ничего не нужно.
Взгляните на perlrun :
-p
заставляет Perl выполнять следующий цикл вокруг вашей программы, который заставляет его перебирать аргументы имени файла наподобие sed:
LINE: while (<>) { ... # здесь идет ваша программа } continue {{{1 }} print or die "-p destination: $! \ n"; }
Если файл, названный аргументом, не может быть открыт по какой-либо причине, Perl предупреждает вас об этом, и переходит к следующему файлу.Обратите внимание, что линии печатаются автоматически. Ошибка, возникающая во время печати, считается фатальной. Чтобы подавить печать, используйте переключатель -n. -P отменяет переключатель -n.
Блоки BEGIN и END могут использоваться для захвата управления до или после неявного цикла, как в awk.
Итак, просто возьмите этот кусок кода, вставьте свой код в строку «# ваша программа идет сюда», и альт, ваш скрипт готов!
Таким образом, это будет:
#!/usr/bin/perl -w
use strict; # or use 5.012 if you've got newer perls
while (<>) {
s/(\d+)/localtime($1)/e
} continue {
print or die "-p destination: $!\n";
}
Здесь есть несколько хороших ответов, если вы хотите сохранить однострочный сценарий и, возможно, даже расширить его, но самая простая вещь, которая могла бы сработать, это просто:
#!/usr/bin/perl -p
s/(\d+)/localtime($1)/e
Perl распознает параметры в hashbang в строке сценария, поэтому вместо того, чтобы полностью писать цикл, вы можете просто продолжить выполнение неявного цикла с -p.
Но написав цикл явно и используя -w и "use strict;" хороши, если вы планируете использовать его в качестве отправной точки для написания более длинного сценария.
Этот действительно легко хранить в скрипте!
#! /usr/bin/perl -p
s/(\d+)/localtime($1)/e
Опция -e
вводит код Perl для выполнения - который можно рассматривать как сценарий в командной строке - поэтому отбросьте ее и поместите код в тело. Оставьте -p
в строке shebang (#!
).
В целом, безопаснее всего придерживаться не более одного "блока" опций в строке shebang. Если вам нужно больше, вы всегда можете бросить их эквиваленты в блок BEGIN {}
.
Не забудьте chmod +x ~/bin/nagiostime.pl
Вы можете стать немного вычурнее и встроить часть tail
:
#! /usr/bin/perl -p
BEGIN {
die "Usage: $0 [ nagios-log ]\n" if @ARGV > 1;
my $log = @ARGV ? shift : "/var/log/nagios/nagios.log";
@ARGV = ("tail -f '$log' |");
}
s/(\d+)/localtime($1)/e
Это работает, потому что код, написанный за вас -p
, использует "волшебный" (2-аргументный) open
Perl, который специально обрабатывает трубы.
Без аргументов он преобразует nagios.log
, но вы также можете указать другой файл журнала, например, ,
$ ~/bin/nagiostime.pl /tmp/other-nagios.log
#!/usr/bin/env perl
while(<>) {
s/(\d+)/localtime($1)/e;
print;
}
Цикл while и печать - это то, что -p делает автоматически за вас.
У Роберта есть «настоящий» ответ выше, но он не очень практичный. Переключатель -p творит немного волшебства, а другие параметры обладают еще большей магией (например, проверьте логику флага -i). На практике я бы просто создал псевдоним / функцию bash для обтекания единственной строки, а не преобразовывал ее в скрипт.
В качестве альтернативы, вот ваш единственный лайнер в виде скрипта: :)
#!/usr/bin/bash
# takes any number of arguments: the filenames to pipe to the perl filter
tail -f $@ | perl -pe 's/(\d+)/localtime($1)/e'