一行程序应该:
- 解决现实世界的问题
- 没有广泛的神秘(应该是很容易理解和复制)
- 值得需要写它的时候(不要太聪明)
我在寻找实用的技巧和窍门(互补例子perldoc perlrun
)。
一行程序应该:
我在寻找实用的技巧和窍门(互补例子perldoc perlrun
)。
请参阅我的幻灯片“A图鉴Perl的命令行选项。”
你可能不认为这是Perl的,但我用ACK宗教(这是一个聪明的grep替换用Perl编写的),并且让我的编辑,例如,所有这些访问我们的API的特定部分的我的Perl的测试:
vim $(ack --perl -l 'api/v1/episode' t)
作为一个侧面说明,如果你使用vim,你可以在编辑器的缓存运行所有的测试 。
对于一些具有比较明显的(如果简单)的Perl,我需要知道测试程序有多少使用了在T / lib中/ TestPM目录测试夹具(我已经削减为清楚起见,命令)。
ack $(ls t/lib/TestPM/|awk -F'.' '{print $1}'|xargs perl -e 'print join "|" => @ARGV') aggtests/ t -l
注意如何“加入”原来的结果为正则表达式来喂ACK。
问题 :媒体播放器不会自动加载,由于他们的名字从字幕相应的视频文件不同。
解决方案 :重命名(字幕文件)的所有* .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 -pe's/([\d.]+)/localtime $1/e;' access.log
有了小的调整,您可以stackoverflow.com访问和打印只有那些线条,与人类可读的日期,使其只显示与你感兴趣的关键字线。以下的手表。 为了它,我给它的输出更加有用tail -f
,这样我就可以实时看到访问:
tail -f access.log | perl -ne's/([\d.]+)/localtime $1/e,print if /stackoverflow\.com/'
使用的常见的成语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
读取空分隔的记录而不是行,但我平时非常有信心,我的文件名不包含嵌入的换行符。)
从收集在一个地方的所有答案的俏皮话:
perl -pe's/([\d.]+)/localtime $1/e;' access.log
ack $(ls t/lib/TestPM/|awk -F'.' '{print $1}'|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)'
见他们的描述相应的答案。
Perl的一个班轮我最常使用的是Perl计算器
perl -ple '$_=eval'
一个在$工作的最大带宽猪的就是下载网页的广告,所以我在寻找低挂水果等待挑选。 我已经摆脱了谷歌的广告,现在我有微软在我行的景点。 于是我运行日志文件的尾部,并挑选出感兴趣的线路:
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的管道确实是通过设置自动冲洗,以真正的开始,因此,任何被采取行动立即打印出来。 否则,它输出分块向上和一个接收一批行的当输出缓冲器填满。 -a开关分裂在白色空间中的每个输入线路,并保存在阵列@F结果(功能由AWK的能力启发,输入记录分割为它的$ 1,$ 2,$ 3 ...变量)。
它检查在该行的第7场中是否包含URI我们寻求(使用\ Q可为我们节省逃逸无趣元字符的疼痛)。 如果找到匹配,它漂亮,打印时间,源IP地址和从远程站点返回的字节数。
该时间按在第一场划时代的时间和使用“本地时间”把它分解成其组成部分(小时,分,秒,日,月,年)获得。 它采用前三个元素的切片返回,秒针,分针和时针,并逆转以获得时,分,秒。 这个被返回为三个元件阵列,与所述第三(IP地址)的从原始@F阵列片和第五(尺寸)沿。 这五个参数传递到sprintf的哪些格式的结果。
@胡椒博士
在删除重复的文字 $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;
响应于Ovids VIM / ACK组合:
我也是经常在寻找的东西,然后想打开Vim中匹配的文件,所以我前一段时间自己做了一点点快捷方式(在ZSH作品而已,我认为):
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。 会发生什么事是那ZSH追加和“-l”列出文件名只有当命令“ACK”开始。 然后,它把“$(...)”,围绕命令和“VIM”在它的前面。 那么整个事情被执行。
我用这个相当频繁大纪元迅速转化为有用的邮戳。
perl -l -e 'print scalar(localtime($ARGV[0]))'
请在你的shell别名:
alias e2d="perl -le \"print scalar(localtime($ARGV[0]));\""
然后管中的时期号到别名。
echo 1219174516 | e2d
在Unix / Linux的许多程序和实用工具使用划时代值来表示时间,所以这已经证明是非常宝贵的我。
除去在路径变量重复:
set path=(`echo $path | perl -e 'foreach(split(/ /,<>)){print $_," " unless $s{$_}++;}'`)
删除MS-DOS行结束。
perl -p -i -e 's/\r\n$/\n/' htdocs/*.asp
我常常需要看到,而shell脚本路径的可读版本。 下面的单行打印在它自己线上的每个路径条目。
随着时间的推移这一个班轮经历了几个阶段的发展:
UNIX(第1版):
perl -e 'print join("\n",split(":",$ENV{"PATH"}))."\n"'
视窗(第2版):
perl -e "print join(qq(\n),split(';',$ENV{'PATH'})).qq(\n)"
在UNIX /视窗(使用Q / QQ尖端从@ JF-塞巴斯蒂安)(第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 -nle "print ' Stack Overflow ' . $1 . ' (no change)' if /\s{20,99}([0-9,]{3,6})<\/div>/;" "SO.html" >> SOscores.txt
这是假设用户页面已经被下载到文件SO.html。 我使用wget用于此目的。 这里的符号是Windows的命令行; 这将是Linux或Mac OS X的输出略有不同的附加到一个文本文件中。
我用它在BAT脚本对四个地点在家庭自动化声誉的采样:堆栈溢出,服务器故障,超级用户和Meta堆栈溢出。
其中最近的一次派,在我的〜/ 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; }'
你会用它对付一个日志文件的尾巴,它会打印被outputed线的速度。
想知道你多少命中每秒让你的网络服务器? 尾-f日志| this_script。
获得从人类可读输出du
,按大小排序:
perl -e '%h=map{/.\s/;7x(ord$&&10)+$`,$_}`du -h`;print@h{sort%h}'
过滤器空白分隔节(名称/值对的列表),单独地分选各节流:
perl -00 -ne 'print sort split /^/'
网络管理员必须尤其是在使用思科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,请建议是否应该以任何方式对正确的使用方法进行修改。
展开所有标签为空格: perl -pe'1while+s/\t/" "x(8-pos()%8)/e'
在Vim的RET:当然,这可能是与完成:设置等。
我有与我确定文本部分的标签列表。 主列表的格式为:
text description {tag_label}
这一点很重要的是, {tag_label}
不重复。 因此,有这个漂亮的简单的脚本:
perl -ne '($c) = $_ =~ /({.*?})/; print $c,"\n" ' $1 | sort | uniq -c | sort -d
我知道我可以做一大堆的外壳或Perl,但这是浮现在脑海的第一件事。
我常常不得不表格数据中的配置文件转换。 对于例如,网络布线厂商提供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
等等。 同样的任务重新出现在哪里需要一个表格数据与他们的字段名称预先考虑并调换到一个平面结构的各种管理任务的几种形式。 我见过一些DBA的浪费了大量的时间准备从Excel工作表中的SQL语句。 它可以使用这个简单的一行来实现。 只需使用您喜欢的电子表格工具保存在CSV格式的表格数据,并运行此需要一行代码。 在标题行的字段名被预置到单个单元格的值,所以你可能要修改它来满足您的要求。
perl -F, -lane "if ($.==1) {@keys = @F} else{print @keys[$_].$F[$_] foreach(0..$#F)} "
需要说明的是,没有一个字段名称或值应该包含任何逗号。 这也许可以进一步阐述赶上一行这样的例外,请尽可能改善这一点。
这是一个我有收集压缩日志文件打交道时放在手边:
open STATFILE, "zcat $logFile|" or die "Can't open zcat of $logFile" ;
在一段时间后我发现,什么我想用Perl这样做是足够短,可以在命令行上完成与“perl的-e”可以做的更好,更容易和更快地引用没有的麻烦正常zsh的特性,。 如上面的例子可以做这样的:
for foo in *.avi; mv *.srt ${foo:r}.srt
UPDATE
上述onliner是obiously错了,对不起,不仔细阅读。 下面是正确的版本:
srt=(*.srt); for foo in *.avi; mv $srt[1] ${foo:r}.srt && srt=($srt[2,-1])