Subscribed unsubscribe Subscribe Subscribe

反転ワンライナーいろいろ

Perl OneLiner

引数の順番を反転させる

@ARGVを素直にreverseさせると、こうかな。

$ perl -le 'print for reverse @ARGV' hoge fuga piyo
piyo
fuga
hoge

改行させたくないなら

$ perl -le 'print join " ", reverse @ARGV' hoge fuga piyo
piyo fuga hoge

が普通だろうか。

$ perl -le '@_ = reverse @ARGV; print "@_"' hoge fuga piyo
piyo fuga hoge

とか、

$ perl -le '$,=$"; print reverse @ARGV' hoge fuga piyo
piyo fuga hoge

とか。



@ARGVを使わずにpopで逆から取り出す方法も。

$ perl -le 'print while $_ = pop' hoge fuga piyo
piyo
fuga
hoge

改行させないようにすると難しい。

$ perl -l40e 'print while $_ = pop' hoge fuga piyo
piyo fuga hoge $

これでは最後にもスペースが入ってしまうし改行ができない。どうしたものか。

引数の文字列を反転させる

順番ではなく、受け取った文字列そのものを反転させてみよう。

$ perl -le 'print scalar reverse shift' hoge
egoh

"scalar"をつけないとreverseがLISTコンテキストで解釈されてしまい、文字列の反転がなされないようだ。
SCALARコンテキストで解釈してもうらうためなら、こんな方法でも良いのかも。

$ perl -le 'print "" . reverse shift' hoge
egoh

空文字列と連結しようとすることでSCALARコンテキストに。


日本語などが入ってくるとめんどくさいことになる。

$ perl -MEncode -le 'print encode_utf8 reverse decode_utf8 shift' "ほげふがぴよ"
よぴがふげほ

短くしようとしたら、

$ perl -MEncode -C2 -le 'print "" . reverse decode_utf8 shift' "ほげふがぴよ"
よぴがふげほ

とか?


shiftの代わりに"@ARGV"とかにすれば引数全体を1つの文字列として反転できる。

$ perl -le 'print scalar reverse "@ARGV"' hoge fuga piyo
oyip aguf egoh
$ perl -MEncode -C2 -le 'print "" . reverse decode_utf8 "@ARGV"' "ほげ" "ふが" "ぴよ"
よぴ がふ げほ

テキストファイルを反転させる

例えば以下のようなテキストファイルに対して。

$ cat hoge.txt
foo,hoge
bar,fuga
baz,piyo
左右の反転

各行をそれぞれ反転させてやればいいだけ。
ただし、ファイル入力にはperlコマンドラインオプションを使うことができるので便利。
"-n"オプションを使って読み込めば、

$ perl -lne 'print scalar reverse' hoge.txt
egoh,oof
aguf,rab
oyip,zab

"-p"オプションなら、さらに短く。

$ perl -lpe '$_ = reverse' hoge.txt
egoh,oof
aguf,rab
oyip,zab
上下の反転

下の行から順に表示する、いわゆるtacコマンド的なもの。
普通にやれば、こんなカンジ。

$ perl -e 'print reverse <>' hoge.txt
baz,piyo
bar,fuga
foo,hoge


某golfの世界では、こんな裏技(?)があるらしい。

$ perl -pe '$\=$_.$\}{' hoge.txt
baz,piyo
bar,fuga
foo,hoge

"-MO=Deparse"ではちょっと違うけど、"-p"オプションを付けると

while (defined($_ = <ARGV>)) {
    CODE
    print $_;
}

と解釈されるようになるそうで。"CODE"の部分が"-e"のオプションで渡される部分になる。
ので、"-e"のオプション引数で '$\=$\.$_}{' というものを与えると…

while (defined($_ = <ARGV>)) {
    $\ = $_ . $\
}
{
    print $_;
}

と解釈されることになる。
結果的にwhile文内でprintは実行されず、特殊変数 $\ に各行の内容が前方に連結されていくだけになる。最後まで読み出し終わって $_ がundefになってから、毎回実行されるはずだったprint文が一度だけ呼ばれるようになる。 $_ はundefでも、 $\ にすべての行を前方に連結していったものが入っているので、それが出力される(特殊変数は $\ は出力レコード末尾セパレータで、デフォルトでは空文字だけどprint文の末尾に必ず付け足されるようになっている)。
こうしてファイルを上下反転したものを出力できる、とのこと。なんという魔法…

まるごと反転

"-0"オプションを指定すればファイルの内容すべてを1つの文字列として読み込んでくれる。

$ perl -l -0pe '$_ = reverse' hoge.txt

oyip,zab
aguf,rab
egoh,oof