Однострочник должен:
Ищу практические советы и рекомендации (дополнительные примеры для perldoc perlrun).
Спасибо. Я исправил заголовок. Время для моей последней трапезы еще не пришло :)





Проблема: медиаплеер не загружает субтитры автоматически, так как их имена отличаются от соответствующих видеофайлов.
Решение: переименовать все * .srt (файлы с субтитрами), чтобы они соответствовали * .avi (файлы с видео).
perl -e'while(<*.avi>) { s/avi$/srt/; rename <*.srt>, $_ }'
ПРЕДОСТЕРЕЖЕНИЕ: порядок сортировки исходных файлов видео и субтитров должен быть одинаковым.
Вот более подробная версия вышеупомянутого однострочника:
my @avi = glob('*.avi');
my @srt = glob('*.srt');
for my $i (0..$#avi)
{
my $video_filename = $avi[$i];
$video_filename =~ s/avi$/srt/; # 'movie1.avi' -> 'movie1.srt'
my $subtitle_filename = $srt[$i]; # 'film1.srt'
rename($subtitle_filename, $video_filename); # 'film1.srt' -> 'movie1.srt'
}
Пожалуйста, посмотрите мои слайды для «Полевое руководство по параметрам командной строки Perl».
Слайд с `-e examples ': в Windows я предпочитаю q () и qq () вместо кавычек. Это позволяет мне использовать ту же однострочную версию Linux, заменяя только две внешние кавычки. Windows: perl -E "сказать q (Привет, мир)". Linux: perl -E'say q (Привет, мир) '
Мертвая ссылка, что ...
Зеркальная ссылка: web.archive.org/web/20120916013412/http://petdance.com/perl/…
В какой-то момент я обнаружил, что все, что я хотел бы сделать с Perl, что достаточно короткое, чтобы быть сделано в командной строке с помощью «perl -e», можно сделать лучше, проще и быстрее с помощью обычных функций оболочки Z без хлопот с цитированием. Например. приведенный выше пример можно сделать так:
srt=(*.srt); for foo in *.avi; mv $srt[1] ${foo:r}.srt && srt=($srt[2,-1])
glob-in-scalar-context действительно очень легко ошибиться; по возможности его следует избегать.
Разве новая версия не рассинхронизируется при сбое MV?
Что ж, сама идея этой штуки несколько нестабильна, поскольку предполагает, что для каждого .avi есть .srt и что оба, при сортировке по алфавиту, каждая пара avi / srt находится в одной и той же позиции в списках. Однако вы можете заменить && на; и обвяжите его фигурными скобками. ;)
Файлы журнала Squid. Они классные, правда? За исключением того, что по умолчанию в качестве поля времени у них есть секунды с эпохи. Вот однострочный файл, который читает из файла журнала squid и преобразует время в удобочитаемую дату:
perl -pe's/([\d.]+)/localtime /e;' access.log
С помощью небольшой настройки вы можете сделать так, чтобы он отображал только строки с интересующим вас ключевым словом. Следующие часы для stackoverflow.com получают доступ и печатают только эти строки с удобочитаемой датой. Чтобы сделать его более полезным, я даю ему вывод tail -f, чтобы я мог видеть доступы в реальном времени:
tail -f access.log | perl -ne's/([\d.]+)/localtime /e,print if /stackoverflow\.com/'
Одна из самых больших проблем с пропускной способностью на работе - это загрузка веб-рекламы, поэтому я смотрю на низко висящие плоды, которые ждут, чтобы их сорвали. Я избавился от рекламы Google, теперь у меня в поле зрения Microsoft. Итак, я просматриваю файл журнала и выбираю интересующие строки:
tail -F /var/log/squid/access.log | \
perl -ane 'BEGIN{$|++} $F[6] =~ m{\Qrad.live.com/ADSAdClient31.dll}
&& printf "%02d:%02d:%02d %15s %9d\n",
sub{reverse @_[0..2]}->(localtime $F[0]), @F[2,4]'
Конвейер Perl начинает с установки для autoflush значения true, чтобы все, что было выполнено, немедленно распечатывалось. В противном случае вывод разбивается на части, и при заполнении буфера вывода получается пакет строк. Ключ -a разделяет каждую строку ввода на пробел и сохраняет результаты в массиве @F (функциональность основана на способности awk разбивать входные записи на переменные $ 1, $ 2, $ 3 ...).
Он проверяет, содержит ли седьмое поле в строке искомый URI (используя \ Q, чтобы избавить нас от боли, связанной с избеганием неинтересных метасимволов). Если совпадение найдено, он выводит время, IP-адрес источника и количество байтов, возвращаемых с удаленного сайта.
Время получается путем взятия времени эпохи в первом поле и использования «местного времени» для разбивки его на составляющие (час, минута, секунда, день, месяц, год). Он берет часть из первых трех возвращаемых элементов, секунд, минут и часов, и меняет порядок, чтобы получить часы, минуты и секунды. Он возвращается как трехэлементный массив вместе с фрагментом третьего (IP-адрес) и пятого (размер) из исходного массива @F. Эти пять аргументов передаются в sprintf, который форматирует результаты.
Вы можете не думать об этом как о Perl, но я неукоснительно использую подтверждать (это умная замена grep, написанная на Perl), и это позволяет мне редактировать, например, все мои тесты Perl, которые обращаются к определенной части нашего API:
vim $(ack --perl -l 'api/v1/episode' t)
В качестве примечания: если вы используете vim, вы можете запустить все тесты в буферах вашего редактора.
Для чего-то с более очевидным (хотя и простым) Perl мне нужно было знать, сколько тестовых программ использовали тестовые инструменты в каталоге t / lib / TestPM (я сократил команду для ясности).
ack $(ls t/lib/TestPM/|awk -F'.' '{print }'|xargs perl -e 'print join "|" => @ARGV') aggtests/ t -l
Обратите внимание, как «объединение» превращает результаты в регулярное выражение для передачи на подтверждение.
ссылка use.perl.org/~Ovid/journal/37470 не работает
В ответ на Комбинация Vim / ack Овидия:
Я тоже часто что-то ищу, а затем хочу открыть соответствующие файлы в Vim, поэтому некоторое время назад я сделал себе небольшой ярлык (работает только в Z оболочка, я думаю):
function vimify-eval; {
if [[ ! -z "$BUFFER" ]]; then
if [[ $BUFFER = 'ack'* ]]; then
BUFFER = "$BUFFER -l"
fi
BUFFER = "vim $($BUFFER)"
zle accept-line
fi
}
zle -N vim-eval-widget vimify-eval
bindkey '^P' vim-eval-widget
Это работает так: я ищу что-то с помощью ack, например ack some-pattern. Я смотрю на результаты и, если они мне нравятся, нажимаю стрелку вверх, чтобы снова получить строку подтверждения, а затем нажимаю Ctrl + P. Что происходит тогда, так это то, что оболочка Z добавляет и «-l» для перечисления имен файлов, только если команда начинается с «ack». Затем он помещает "$ (...)" вокруг команды и "vim" перед ней. Затем все выполняется.
Вот один из них, который мне пригодится при работе с коллекцией сжатых файлов журнала:
open STATFILE, "zcat $logFile|" or die "Can't open zcat of $logFile" ;
Однострочность означает целую программу на одной строке, а не одну полезную строку программы.
Я бы сам разделил это на 2 или более строк.
Я использую это довольно часто, чтобы быстро преобразовать времена эпох в полезную метку даты.
perl -l -e 'print scalar(localtime($ARGV[0]))'
Создайте псевдоним в своей оболочке:
alias e2d = "perl -le \"print scalar(localtime($ARGV[0]));\""
Затем передайте псевдониму номер эпохи.
echo 1219174516 | e2d
Многие программы и утилиты в Unix / Linux используют значения эпох для обозначения времени, поэтому для меня это оказалось бесценным.
Чтобы получить удобочитаемую метку времени из секунд эпохи, вы также можете использовать дату GNU со знаком @: date --date = @ 1219174516
Фильтрует поток строф, разделенных пробелами (списки пар имя / значение), сортировка каждой строфы индивидуально:
perl -00 -ne 'print sort split /^/'
sort() поместит пустые строки в начало абзаца. Думаю, вы на самом деле имеете в виду следующее: perl -00 -ne '($ n, @a) = sort split / ^ /; print @a, $ n 'Оба однострочных сообщения завершатся ошибкой, если после последнего абзаца нет новой строки.
Разверните все вкладки до пробелов: perl -pe'1while+s/\t/" "x(8-pos()%8)/e'
Конечно, это можно сделать с помощью: set et,: ret в Vim.
perl -pe'1 while + s / \ t / "" x (8- (pos)% 8) / e 'Скобки обязательны.
Удалите дубликаты в переменной пути:
set path=(`echo $path | perl -e 'foreach(split(/ /,<>)){print $_," " unless $s{$_}++;}'`)
Что такое разделитель между путями в $ path? Смотрите мой ответ.
Чаще всего я использую однострочник Perl - это калькулятор Perl.
perl -ple '$_=eval'
Если вы используете Perl 5.10, вы можете запустить perl -plE '$ _ = eval', чтобы включить функции 5.10.
@Dr Pepper
Удалите дубликаты буквальный в $PATH:
$ export PATH=$(perl -F: -ane'print join q/:/, grep { !$c{$_}++ } @F'<<<$PATH)
Печатайте уникальные чистые пути из переменной среды %PATH% (это не касается ../ и подобных, замените File::Spec->rel2abs на Cwd::realpath, если это желательно). Это не однострочный, чтобы быть более портативным:
#!/usr/bin/perl -w
use File::Spec;
$, = "\n";
print grep { !$count{$_}++ }
map { File::Spec->rel2abs($_) }
File::Spec->path;
Спасибо, что показали мне это, я искал для этого более короткий однострочник. В моей среде пробел является разделителем при использовании строчной буквы $ path. Лучше использовать верхний регистр $ PATH?
В моей оболочке (bash) $ path и $ PATH - разные переменные (имена чувствительны к регистру: $ a = 2; A = 3; echo $ (($ a * $ A)) Это печатает '6'.
Дубликаты можно было удалить с помощью комбинации программ tr, sort, uniq, cut и пайпа.
Но использование tr, sort и т. д. Изменяет порядок путей, что может вызвать нежелательные побочные эффекты.
В ZSH переменная path связана с переменной PATH, поэтому PATH всегда является элементами path, соединенными двоеточием, а path всегда является массивом, содержащим фрагменты PATH, разделенные столбцом. Чтобы сделать их уникальными, просто примените модификатор -U к одной из переменных: typeset -U PATH
Распространенная идиома использования find ... -exec rm {} \; для удаления набора файлов где-нибудь в дереве каталогов не особенно эффективна, поскольку она выполняет команду rm один раз для каждого найденного файла. Одна из моих привычек, рожденных в те дни, когда компьютеры были не такими быстрыми (dagnabbit!), - заменить множество вызовов rm одним вызовом perl:
find . -name '*.whatever' | perl -lne unlink
Часть командной строки perl читает список файлов, созданных * find, по одному в каждой строке, обрезает новую строку и удаляет файл с помощью встроенной в perl функции unlink(), которая принимает $_ в качестве аргумента, если явный аргумент не указан. . ($_ устанавливается для каждой строки ввода благодаря флагу -n.) (* В наши дни большинство команд find по умолчанию выполняет -print, поэтому я могу опустить эту часть.)
Мне нравится эта идиома не только из-за эффективности (возможно, менее важной в наши дни), но и из-за того, что в ней меньше сочетаний клавиш / неудобных клавиш, чем при вводе традиционной последовательности -exec rm {} \;. Это также позволяет избежать проблем с цитированием, вызванных именами файлов с пробелами, кавычками и т. д., Которых у меня много. (Более надежная версия может использовать опцию find-print0, а затем попросить perl читать записи с разделителями NULL вместо строк, но я обычно довольно уверен, что мои имена файлов не содержат встроенных символов новой строки.)
Я использую xargs для решения этой проблемы еще до того, как Perl засветился в глазах Ларри :-).
Справедливо, потому что это тема, связанная с Perl; но другая более надежная версия POSIX может использовать find ... -print0 | xargs -0 -- rm или GNU findutils: find ... --exec rm {} +⁽ʳᵉᶠ⁾
Все однострочные ответы собраны в одном месте:
perl -pe's/([\d.]+)/localtime /e;' access.log
ack $(ls t/lib/TestPM/|awk -F'.' '{print }'|xargs perl -e 'print join "|" => @ARGV')
aggtests/ t -l
perl -e'while(<*.avi>) { s/avi$/srt/; rename <*.srt>, $_ }'
find . -name '*.whatever' | perl -lne unlink
tail -F /var/log/squid/access.log | perl -ane 'BEGIN{$|++} $F[6] =~ m{\Qrad.live.com/ADSAdClient31.dll}
&& printf "%02d:%02d:%02d %15s %9d\n", sub{reverse @_[0..2]}->(localtime $F[0]), @F[2,4]'
export PATH=$(perl -F: -ane'print join q/:/, grep { !$c{$_}++ } @F'<<<$PATH)
alias e2d = "perl -le \"print scalar(localtime($ARGV[0]));\""
perl -ple '$_=eval'
perl -00 -ne 'print sort split /^/'
perl -pe'1while+s/\t/" "x(8-pos()%8)/e'
tail -f log | perl -ne '$s=time() unless $s; $n=time(); $d=$n-$s; if ($d>=2) { print qq
($. lines in last $d secs, rate ),$./$d,qq(\n); $. =0; $s=$n; }'
perl -MFile::Spec -e 'print join(qq(\n),File::Spec->path).qq(\n)'
См. Соответствующие ответы для их описания.
Удалите окончания строк MS-DOS.
perl -p -i -e 's/\r\n$/\n/' htdocs/*.asp
1. -i требует суффикса, например, -i.bak. 2. Не работает в Windows.
Мне было интересно, как сделать Perl pie в Windows. Спасибо за совет.
Один из последних однострочников, нашедших место в моем ~ / bin:
perl -ne '$s=time() unless $s; $n=time(); $d=$n-$s; if ($d>=2) { print "$. lines in last $d secs, rate ",$./$d,"\n"; $. =0; $s=$n; }'
Вы можете использовать его против хвоста файла журнала, и он будет печатать скорость вывода строк.
Хотите знать, сколько посещений в секунду вы получаете на своих веб-серверах? хвост -f журнал | this_script.
Это миниатюрный просмотрщик каналов (pv) <ivarch.com/programs/pv.shtml>. Но ваш однострочник работает в Windows.
Извлечение репутации Stack Overflow без необходимости открывать веб-страницу:
perl -nle "print ' Stack Overflow ' . . ' (no change)' if /\s{20,99}([0-9,]{3,6})</div>/;" "SO.html" >> SOscores.txt
Предполагается, что страница пользователя уже загружена в файл SO.html. Для этого я использую wget. Обозначения здесь предназначены для командной строки Windows; он будет немного отличаться для Linux или Mac OS X. Вывод добавляется в текстовый файл.
Я использую его в сценарии BAT, чтобы автоматизировать выборку репутации на четырех сайтах семейства: Переполнение стека, сбой сервера, суперпользователь и переполнение мета-стека.
Получите удобочитаемый вывод от du, отсортированный по размеру:
perl -e '%h=map{/.\s/;7x(ord$&&10)+$`,$_}`du -h`;print@h{sort%h}'
У меня есть список тегов, с помощью которых я идентифицирую части текста. Главный список имеет формат:
text description {tag_label}
Важно, чтобы {tag_label} не дублировался. Итак, есть этот красивый простой скрипт:
perl -ne '($c) = $_ =~ /({.*?})/; print $c,"\n" ' | sort | uniq -c | sort -d
Я знаю, что мог бы сделать все в оболочке или Perl, но это было первое, что пришло мне в голову.
perl -ne'$f{}++ while /({.*?})/g; END{ print "$f{$_} $_\n" for (sort {$f{$a} <=> $f{$b}} keys %f) }' . Вы правы, что для таких задач достаточно первой вещи. кстати, вы уверены, что в каждой строке может быть только один тег?
Мне часто нужно видеть читаемую версию PATH во время написания сценария оболочки. Следующие однострочные символы печатают каждую запись пути в отдельной строке.
Со временем этот однострочник прошел несколько этапов:
Unix (версия 1):
perl -e 'print join("\n",split(":",$ENV{"PATH"}))."\n"'
Windows (версия 2):
perl -e "print join(qq(\n),split(';',$ENV{'PATH'})).qq(\n)"
Оба Unix / Windows (с использованием подсказки q / qq от @ j-f-sebastian) (версия 3):
perl -MFile::Spec -e 'print join(qq(\n), File::Spec->path).qq(\n)' # Unix
perl -MFile::Spec -e "print join(qq(\n), File::Spec->path).qq(\n)" # Windows
perl -MFile::Spec -E '$,=qq(\n); say File::Spec->path'
perl -MFile::Spec::Functions -E '$,=qq(\n); say path'
@ J.F. Себастьян: При запуске с -E я получаю Unrecognized switch: -E (-h will show valid options). как в Windows, так и в UNIX. Я использую perl v5.8.8 на обеих платформах.
-E включает дополнительные функции, такие как say() от 5.10 (с 2007 г.).
@ J.F. Себастьян: Спасибо, это полезный лакомый кусочек!
Сетевые администраторы имеют тенденцию неправильно настраивать «адрес подсети» как «адрес хоста», особенно при использовании автоматического предложения Cisco ASDM. Этот простой однострочный сканер сканирует файлы конфигурации на предмет любых таких ошибок конфигурации.
неправильное использование: permit host 10.1.1.0
правильное использование: permit 10.1.1.0 255.255.255.0
perl -ne "print if /host ([\w\-\.]+){3}\.0 /" *.conf
Это было протестировано и использовалось в Windows, пожалуйста, предложите, следует ли его каким-либо образом изменить для правильного использования.
Часто мне приходилось преобразовывать табличные данные в файлы конфигурации. Например, поставщики сетевых кабелей предоставляют запись исправлений в формате Excel, и мы должны использовать эту информацию для создания файлов конфигурации. т.е.
Interface, Connect to, Vlan
Gi1/0/1, Desktop, 1286
Gi1/0/2, IP Phone, 1317
должно стать:
interface Gi1/0/1
description Desktop
switchport access vlan 1286
и так далее. Одна и та же задача повторно появляется в нескольких формах в различных задачах администрирования, где к табличным данным нужно добавить имя их поля и преобразовать в плоскую структуру. Я много раз видел, как некоторые администраторы баз данных тратят свои средства на подготовку своих операторов SQL из таблицы Excel. Этого можно добиться с помощью этого простого однострочника. Просто сохраните табличные данные в формате CSV с помощью вашего любимого инструмента для работы с электронными таблицами и запустите этот однострочный файл. Имена полей в строке заголовка добавляются к отдельным значениям ячеек, поэтому вам, возможно, придется отредактировать его в соответствии с вашими требованиями.
perl -F, -lane "if ($.==1) {@keys = @F} else{print @keys[$_].$F[$_] foreach(0..$#F)} "
Предостережение: ни одно из имен или значений полей не должно содержать запятых. Возможно, это может быть доработано, чтобы улавливать такие исключения в одну строку, пожалуйста, улучшите это, если возможно.
«последний» означает «окончательный», например, я никогда больше не напишу другого. Этого не случится. Я буду продолжать писать однострочники Perl, пока это будет приниматься подсказкой. Возможно, вы имели в виду «последний».