ワンライナーは次のようにする必要があります。
- 現実の問題を解決する
- 広範に不可解ではない(理解しやすく、再現しやすいものにする必要があります)
- それを書くのにかかる時間の価値があります(あまり賢くないはずです)
実用的なヒントとコツを探しています(の補足例perldoc perlrun
)。
ワンライナーは次のようにする必要があります。
実用的なヒントとコツを探しています(の補足例perldoc perlrun
)。
「Perlコマンドラインオプションのフィールドガイド」については、私のスライドを参照してください。
Squid ログ ファイル。彼らは素晴らしいですね。デフォルトを除いて、時間フィールドとしてエポックからの秒数があります。以下は、squid のログ ファイルから読み取り、時刻を人間が判読できる日付に変換するワンライナーです。
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/'
問題:メディアプレーヤーは、名前が対応するビデオファイルと異なるため、字幕を自動的にロードしません。
解決策:すべての* .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 とは考えないかもしれませんが、私はackを宗教的に使用しており (これは Perl で書かれたスマートな grep 置換です)、これにより、たとえば、API の特定の部分にアクセスするすべての Perl テストを編集できます。
vim $(ack --perl -l 'api/v1/episode' t)
補足として、vim を使用すると、エディターの buffers ですべてのテストを実行できます。
より明白な (単純な場合) Perl を使用する場合、t/lib/TestPM ディレクトリ内のテスト フィクスチャを使用したテスト プログラムの数を知る必要がありました (わかりやすくするためにコマンドを省略しました)。
ack $(ls t/lib/TestPM/|awk -F'.' '{print $1}'|xargs perl -e 'print join "|" => @ARGV') aggtests/ t -l
「結合」がどのように結果を正規表現に変換して ack にフィードするかに注意してください。
find ... -exec rm {} \;
ディレクトリ ツリー内のどこかにある一連のファイルを削除するために を使用する一般的な慣用句は、rm
見つかったファイルごとにコマンドを 1 回実行するため、特に効率的ではありません。私の習慣の 1 つは、コンピューターがそれほど高速ではなかった時代 (dagnabbit!) から生まれたもので、多くの呼び出しrm
を perl への 1 つの呼び出しに置き換えることです。
find . -name '*.whatever' | perl -lne unlink
コマンド ラインのperl
一部は、 によって発行された* ファイルのリストをfind
1 行に 1 つずつ読み取り、改行を削除し、perl の組み込みunlink()
関数を使用してファイルを削除します$_
。(フラグ$_
のおかげで、入力の各行に設定されます-n
。) (*最近、ほとんどのfind
コマンドは-print
デフォルトで設定されているため、その部分を省略できます。)
-exec rm {} \;
私がこのイディオムを気に入っているのは、その効率性 (おそらく最近ではあまり重要ではない) だけでなく、従来のシーケンスを入力するよりも和音/ぎこちないキーが少ないためです。また、スペースや引用符などを含むファイル名によって引き起こされる引用符の問題も回避できます。(より堅牢なバージョンではfind
's-print0
オプションを使用perl
し、行の代わりに null 区切りのレコードを読み取るように要求する可能性がありますが、通常、ファイル名に改行が含まれていないことを確信しています。)
1か所に集められた回答からのすべてのワンライナー:
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'
$work で最大の帯域幅を消費するのは Web 広告のダウンロードです。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 に保存します (入力レコードを $1、$2、$3... 変数に分割する awk の機能に触発された機能)。
行の 7 番目のフィールドに、探している URI が含まれているかどうかをチェックします (興味のないメタ文字をエスケープする手間を省くために \Q を使用します)。一致が見つかった場合は、時刻、送信元 IP、およびリモート サイトから返されたバイト数がプリティ プリントされます。
時間は、最初のフィールドでエポック時間を取得し、'localtime' を使用してそれを構成要素 (時、分、秒、日、月、年) に分解することによって取得されます。戻り値の最初の 3 つの要素、秒、分、時間のスライスを取得し、順序を逆にして時、分、秒を取得します。これは、元の @F 配列の 3 番目 (IP アドレス) と 5 番目 (サイズ) のスライスと共に、3 つの要素の配列として返されます。これら 5 つの引数は、結果をフォーマットする 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;
Webページを開かずにStackOverflowレピュテーションを抽出する:
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とMacOSXでは少し異なります。出力は、テキストファイルに追加されます。
BATスクリプトで使用して、ファミリー内の4つのサイト(Stack Overflow、Server Fault、Super User、Meta Stack Overflow)でのレピュテーションのサンプリングを自動化します。
私はこれを頻繁に使用して、エポックタイムを便利な日付スタンプにすばやく変換します。
perl -l -e 'print scalar(localtime($ARGV[0]))'
シェルにエイリアスを作成します。
alias e2d="perl -le \"print scalar(localtime($ARGV[0]));\""
次に、エポック番号をエイリアスにパイプします。
echo 1219174516 | e2d
Unix / Linux上の多くのプログラムやユーティリティは、時間を表すためにエポック値を使用しているので、これは私にとって非常に貴重であることがわかりました。
MS-DOS の行末を削除します。
perl -p -i -e 's/\r\n$/\n/' htdocs/*.asp
パス変数の重複を削除します。
set path=(`echo $path | perl -e 'foreach(split(/ /,<>)){print $_," " unless $s{$_}++;}'`)
Ovid の 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
。結果を見て、気に入ったら上向き矢印を押して ack-line を再度取得し、Ctrl+を押しPます。その場合、Z シェルは、コマンドが「ack」で始まる場合にのみ、ファイル名をリストするために「-l」を追加します。次に、コマンドの前後に「$(...)」を置き、その前に「vim」を置きます。その後、全体が実行されます。
シェル スクリプトを実行しているときに、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 の両方 (@jf-sebastian からの q/qq ヒントを使用) (バージョン 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
ネットワーク管理者は、特に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でテストおよび使用されています。正しく使用するために何らかの方法で変更する必要があるかどうかを提案してください。
du
サイズでソートされた、から人間が読める形式の出力を取得します。
perl -e '%h=map{/.\s/;7x(ord$&&10)+$`,$_}`du -h`;print@h{sort%h}'
空白で区切られたスタンザ (名前と値のペアのリスト) のストリームをフィルター処理し、各スタンザを個別に並べ替えます。
perl -00 -ne 'print sort split /^/'
~/bin に配置された最新のワンライナーの 1 つ:
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; }'
ログファイルの末尾に対して使用すると、出力される行の割合が出力されます。
Web サーバーで 1 秒あたりのヒット数を知りたいですか? テール -f ログ | this_script.
テキストの一部を識別するタグのリストがあります。マスター リストの形式は次のとおりです。
text description {tag_label}
{tag_label}
重複しないことが重要です。だから、この素晴らしい単純なスクリプトがあります:
perl -ne '($c) = $_ =~ /({.*?})/; print $c,"\n" ' $1 | sort | uniq -c | sort -d
シェルまたは perl ですべてを実行できることは知っていますが、これが最初に思い浮かびました。
すべてのタブをスペースに展開します。perl -pe'1while+s/\t/" "x(8-pos()%8)/e'
もちろん、これは Vim の :set et、:ret で実行できます。
多くの場合、表形式のデータを構成ファイルに変換する必要がありました。たとえば、ネットワーク ケーブル ベンダーはパッチ適用記録を 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)} "
注意点は、フィールド名または値にコンマを含めないことです。おそらく、このような例外を 1 行でキャッチするために、これをさらに詳しく説明することができます。可能であれば、これを改善してください。
これは、コレクションの圧縮ログファイルを処理するときに便利なものです。
open STATFILE, "zcat $logFile|" or die "Can't open zcat of $logFile" ;
ある時、私が Perl でやりたいと思っていたことは、コマンドラインで「perl -e」を使って実行できるほど短いもので、通常の Z シェル機能を使えば、引用の手間をかけずに、より良く、簡単に、より速く実行できることがわかりました。たとえば、上記の例は次のように実行できます。
srt=(*.srt); for foo in *.avi; mv $srt[1] ${foo:r}.srt && srt=($srt[2,-1])