ワンライナー

ちょっと込み入ったことをしたいときに、コマンドラインに直接1行だけのプログラムを書いて、その場で実行しちゃうやつ。

シェルスクリプトでシンボリックリンクからリンク先を取得するには

-> シンボリックリンクのリンク先を取得する

1秒ごとに処理を永久に繰り返すには

while : ; do date; sleep 1; done

URLエンコード / URLデコード

エンコードの例

# URLエンコード
echo あ | ruby -r cgi -ne 'puts CGI.escape $_.chomp' | tr "\n" " " | sed 's/ /%0D%0A/g'

最後の tr "\n" " " | sed s/ /%0D%0A/g は改行を %0D%0A に変換するためのもの。

または

# URLエンコード
echo あ | nkf -WMQ | sed 's/=$//g' | tr -d '\n' | tr = %

nkf -WMQ はよくわからないが文字列が長い場合に改行を入れて、その改行の直前に = を追加するので、途中の sed 's/=$//g' | tr -d '\n' はそれを削除するためのもの。

または、こっちのほうが依存が少なくていいかも。

perl -nle 's/([^\w ])/"%".unpack("H2",$1)/eg; s/ /\+/g; print'

小文字でなくて大文字にしたければ、

perl -nle 's/([^\w ])/"%".uc(unpack("H2",$1))/eg; s/ /\+/g; print'

汎用的なURLエンコードでなくて、URLの中にある日本語だとかだけをいい感じにエンコードしたい場合は

perl -nlpe 's/([^ -~])/"%".unpack("H2",$1)/eg'

実行例

echo 'http://www.example.com/?q=あいうえお&r=Hello' | perl -nlpe 's/([^ -~])/"%".unpack("H2",$1)/eg'
# => http://www.example.com/?q=%e3%81%82%e3%81%84%e3%81%86%e3%81%88%e3%81%8a&r=Hello

デコードの例

# URLデコード
echo %E3%81%82 | tr % = | nkf -WmQ

-W はUTF-8を意味し、 -mQ はURLデコードする。

関連

Unicodeエスケープをデコードするには

Unicodeエスケープは、\u5c71 のようにコードポイントを16進数で表記したもの。

## Perlでのワンライナーの例
$ cat foo.txt | perl -MEncode -nle 's/\\u([a-fA-F0-9]{4})/encode_utf8(chr(hex($1)))/eg; print'

## Rubyでのワンライナーの例
$ cat foo.txt | ruby -ne 'print $_.gsub(/\\u([0-9a-f]{4})/){[$1.hex].pack("U")}'

この例では、16ビットを超えるコードポイントには対応していない。

たくさんのファイルをまとめて less で閲覧するには

-> たくさんのファイルをまとめて less で閲覧するには

改行コードを変換するには

cat ファイル名 | perl -pe 's/\r\n/\n/'

ファイル名に日付が入っているファイルがたくさんあって、日付ごとにファイル数を調べるには

2013-06-22-hogehoge みたいな名前のファイルがたくさんあって、日付ごとにそのファイル数を集計するには、以下のようにする。

for i in 0 1 2 3 4 5 6 7; do date --date "$i days" "+%Y-%m-%d"; done | awk '{print "echo -n " $1 " \"\"; ls " $1 "-* 2>/dev/null | wc -l";}' | sh

出力例

2013-06-22 2
2013-06-23 0
2013-06-24 937
2013-06-25 860
2013-06-26 673
2013-06-27 281
2013-06-28 977
2013-06-29 0

2つのHTTPレスポンスが改行・空白・文字コードの違いを無視して、差分を表示させるワンライナー

diff -uw <(curl -s "http://www.example.com/a/" | nkf -Sw -Lu | sed '/^[[:blank:]]*$/d') <(curl -s "http://www.example.com/b/" | nkf -Lu | sed '/^[[:blank:]]*$/d') | less

Perlで1行ごとになにかをパイプ処理するワンライナー

.... | perl -nle '....'

行は $_ で参照できる。

-n は標準入力を1行ずつ処理する意味。

-lprint で出力の際に最後に改行を付けなくても都度自動で改行してくれる意味。

-e はPerlスクリプトをファイルではなくコマンドラインで直接指定する意味。

Perlで標準入力全体またはファイル全体を $_ に入れて一度に処理するには

-0777 というオプションを付ける。

.... | perl -0777 -nle '....'

入力全体を1つの文字列として $_ で参照できる。

Perlのワンライナーでバッファリングを解除するには

ログファイルなどの tail -f の出力をリアルタイムにperlのワンライナーで処理して表示するには、バッファリングが邪魔してしまうので、バッファリングしないようにすることが必要になる。

ワンライナーのコードの先頭に BEGIN { $| = 1 } を入れればよい。

... | perl -nale 'BEGIN { $| = 1 } $F[12] eq "0" and print $_'

正規分布から無作為に(ランダムに)データ抽出した数列を取得するワンライナー

R言語を使っているが

# 平均50,標準偏差10の正規母集団から100個のデータを取り出す
echo 'rnorm(n=100,mean=50,sd=10)' | R --vanilla --slave  | sed -e 's/^ \+\[[0-9]\+\] //g' -e 's/ /\n/g'

プロセスごとのスレッド数を確認するには

( echo "pid\tname\tthreads"; find /proc/[0-9]*/status | xargs grep -E '^(Name|Threads)' | perl -nle 'if (/^\/proc\/([0-9]+)\/.+:Name:\s+(.+)$/) { $p=$1; $n=$2 } elsif (/^\/proc\/([0-9]+)\/.+:Threads:\s+(.+)$/ && $1==$p) { print "$p\t$n\t$2" }' )

Perlのワンライナーでタブ区切りファイル(TSV)を標準入力から受け付けるには

行を分割するオプション -a と、区切り文字を指定するオプション -F を付ける。スクリプトの中では配列 @F で参照する。Fというのはフィールドの略かな。

# タブ区切りの3カラム目だけを出力
perl -F'\t' -nale 'print $F[2]'
このサイトは筆者(hydrocul)の個人メモの集合です。すべてのページは永遠に未完成です。