Как я могу конвертировать однострочники Perl в полные сценарии? - PullRequest
17 голосов
/ 13 мая 2010

Я нахожу много однострочников 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

Тем не менее, я не могу найти лучший способ быстро добавить этот материал в сценарий. У кого-нибудь есть быстрый способ добавить эти однострочники в сценарии Bash или Perl?

Ответы [ 6 ]

38 голосов
/ 13 мая 2010

Вы можете преобразовать любой однострочный Perl в полный скрипт, передав его через бэкэнд компилятора B::Deparse, который генерирует исходный код Perl:

perl -MO=Deparse -pe 's/(\d+)/localtime($1)/e'

выходы:

LINE: while (defined($_ = <ARGV>)) {
    s/(\d+)/localtime($1);/e;
}
continue {
    print $_;
}

Преимущество этого подхода перед ручным декодированием флагов командной строки заключается в том, что именно так Perl интерпретирует ваш сценарий, так что нет никаких догадок. B::Deparse - это основной модуль, поэтому устанавливать нечего.

8 голосов
/ 13 мая 2010

Взгляните на perlrun :

-p

заставляет Perl выполнять следующий цикл вокруг вашей программы, что заставляет его перебирать аргументы имени файла, что-то вроде sed:

LINE:
while (<>) {
    ... # your program goes here
} continue {
    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";
}
7 голосов
/ 13 мая 2010

Это действительно легко хранить в скрипте!

#! /usr/bin/perl -p
s/(\d+)/localtime($1)/e

Опция -e представляет исполняемый код на Perl, который можно рассматривать как сценарий в командной строке, поэтому отбросьте его и вставьте код в тело. Оставьте -p в строке Шебанга (#!).

В общем, безопаснее всего придерживаться не более одного «набора» опций в строке Шебанга. Если вам нужно больше, вы всегда можете выбросить их эквиваленты в блоке 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, использует "магию" Perl (2 аргумента) open, которая специально обрабатывает каналы.

Без аргументов он преобразует nagios.log, но вы также можете указать другой файл журнала, например, ,

$ ~/bin/nagiostime.pl /tmp/other-nagios.log
4 голосов
/ 13 мая 2010

У Роберта есть «реальный» ответ выше, но он не очень практичен. Ключ -p немного волшебен, а другие опции обладают еще большей магией (например, проверьте логику, стоящую за флагом -i). На практике я просто сделал бы псевдоним / функцию bash, чтобы обернуть вокруг него, вместо того, чтобы конвертировать его в скрипт.

В качестве альтернативы, вот ваш oneliner в виде скрипта::)

#!/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'
3 голосов
/ 13 мая 2010

Здесь есть несколько хороших ответов, если вы хотите, чтобы сценарий был превращен в одну строку и, возможно, даже расширился, но самая простая вещь, которая могла бы сработать, это просто:

#!/usr/bin/perl -p
s/(\d+)/localtime($1)/e

Perl распознает параметры в строке hashbang скрипта, поэтому вместо полной записи цикла вы можете просто продолжить выполнение неявного цикла с -p.

Но, написав цикл явно и используя -w и "используйте строгий;" хорошо, если вы планируете использовать его в качестве отправной точки для написания более длинного сценария.

3 голосов
/ 13 мая 2010
#!/usr/bin/env perl

while(<>) {
    s/(\d+)/localtime($1)/e;
    print;
}

Цикл while и печать - это то, что -p делает для вас автоматически.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...