ワンライナー(One Liner)

Perlにはコマンドライン引数としてスクリプトその物を指定する事が出来る-eオプションが有ります。

Perlではこの仕組みを使ってスクリプトをお手軽に実行する事を通称ワンライナー(One Liner)と呼んでいます。コマンドライン上で指定するので、多くは1行以内にスクリプトが収まっている事からこの様に呼ばれていますが、実際には複数行を指定する事も出来ます。日本語では「1行野郎」と訳する事が多いようです。

  1. -eオプションの最も基本的な使い方

  2. 簡単な実行例を見てみましょう。基本はコマンドライン引数-eに続けて実行したいスクリプトをクォートして指定します。

    $ perl -e 'print "Hello, World\n"'
    Hello, World

    冒頭でも触れましたが、One Linerと言いながらスクリプトは複数行書く事も出来ます。一つの-e引数の中に複数行のスクリプトを書いてもOKですし、-e引数を複数回指定して、それぞれ1行ずつスクリプトを書いてもOKです。

    • 1つの-eオプションにまとめて指定

    • $ perl -e 'print "Hello, World\n"; print "Hello, World again\n"'
      Hello, World
      Hello, World again

    • 複数の-eオプションにそれぞれ指定

    • $ perl -e 'print "Hello, World\n";' \
      > -e 'print "Hello, World again\n"'
      Hello, World
      Hello, World again

  3. 他の引数と組み合わせて使う

  4. これだけでは余り便利さは感じませんが、他のコマンドライン引数と組み合わせると、どんどん便利になっていきます。

    • -nオプションでwhileを補う

    • perlコマンドの-nオプションは指定したスクリプト全体がwhile(<>) {}で囲んで実行してくれる引数です。

      $ more newfile.txt
      aaa
      bbb
      ccc
      
      $ perl -ne 'print if /a/' newfile.txt
      aaa

      ちなみに-eオプションと無関係に使う事も出来ますが、実際には普通のスクリプトで使う事はまず無いでしょう。

    • -lオプションで読み込み時の改行削除と、書き込み時の改行追加を補う

    • while構文を使って行単位にテキストファイルを処理する際には、読み込み時に改行削除(chomp関数)を行い、書き込み時に改行追加(\n)を行う事が多いと思いますが、これも自動的にやってくれるオプションが有ります。

      -nオプション(または、後述する-pオプション)と-lオプションを組み合わせると、自動的に特殊変数$_にchomp関数が適用されます。またprintする時に自動的に改行が追加されます(実際には$/の内容が$\にコピーされて、その内容が付加されるだけですが...詳細はリファレンスを参照して下さい)。

      以下は、読み込んだCSVの項目順を逆転させるスクリプトの例です。余計な改行を上手く処理してくれています。

      $ more sample.csv 
      aaa,0001
      bbb,0002
      ccc,0003
      $ perl -nle "print join ',',(reverse split /,/)" sample.csv
      0001,aaa
      0002,bbb
      0003,ccc

    • -pオプションで自動出力

    • -nオプションは、スクリプト全体にwhile(<>) {}を補ってくれましたが、-pオプションでは$_の自動出力が加わります。つまり、スクリプト全体にwhile(<>) {} continue {print;}を補ってくれます(printの引数が省略されているので、特殊変数$_の内容が出力されます)。

      以下は、読み込んだCSVの項目の区切り文字をタブに置き換えて出力するスクリプトの例です。特殊変数$_を書きかえる事で、タブに置き換えた内容を自動的に出力してくれます(自分で$_を書き変えていますが、直接printした方が早い気もしますね)。

      $ more sample.csv
      aaa,001
      bbb,002
      ccc,003
      $ perl -ple '$_ = join "\t",(split /,/)' sample.csv
      aaa     001
      bbb     002
      ccc     003

  5. -CオプションでUTF-8文字列を扱う

  6. Perl v5.8.1以降で使用できるオプションです。Perlでは文字列にutf8フラグが立っていないと文字として正しく認識できず、文字数のカウントや正式表現によるマッチングが出来ません(utf8フラグが無いスカラー変数の文字列は単なるバイト列として扱われる)。

    標準入出力や、PerlIOレイヤーのデフォルト設定をUTF-8に設定する事でutf8フラグの上げ下げ(入力にはフラグを設定し、出力時にはフラグを落とす)を自動化する事が出来ます(ただし、UTF-8以外の文字コードを自動的に変換する事はできません)。

    以下の例は-Cオプションを使ってutf8フラグを上げたパターンと、上げないパターンでの比較です。1行のカウント結果の数字が異なる事が分かると思います。

    $ more sample.csv
    aaa,001,あいう
    bbb,002,かきくけ
    ccc,003,さしすせそ
    $ perl -Cio -nle 'print length' sample.csv
    11
    12
    13
    $ perl -nle 'print length' sample.csv
    17
    20
    23

    -Cオプションの後ろに続けて、何の入出力をUTF-8として取り扱うのか指定するオプションを指定します。オプションの意味を以下の表にまとめました。

    -Cオプションに続くUTF-8入出力箇所指定
    オプション-Cの後ろの引数の意味
    I標準入力はUTF-8
    O標準出力はUTF-8
    E標準エラー出力はUTF-8
    SI+O+Eと同じ
    iテキストの入力はUTF-8
    (PerlIOレイヤーのデフォルトがUTF-8)
    oテキストの出力はUTF-8
    (PerlIOレイヤーのデフォルトがUTF-8)
    Di+oと同じ
    A@ARGV(コマンドライン引数)がUTF-8
    Lロケールが適切にUTF-8にセットされていれば、
    I+O+E+i+o+Aと同じ

    最近のロケールがUTF-8化されている環境であれば、-CL指定が良いですね。

  7. モジュールの読み込み指定

  8. -Mオプションに引き続き、モジュール名を指定すると、スクリプト内でuseした事と同じ意味になります。Perlではモジュール無しにはスクリプトは書けないので必須の機能ですね。

    $ perl -MTime::Piece -e 'print localtime->datetime."\n"'
    2010-03-16T20:41:20

  9. その他のオプション引数

  10. 以降は自分では使った事無いのだけど、よく使われるらしいオプション引数を落ち葉拾い的に紹介。

    • -aFオプションで入力された行を自動的に分割

    • CSV形式のデータをsplit関数で分解しながら処理する事が多いと思いますが、-aFオプションはそれを自動的に行ってくれる引数です。Fに引き続き区切り文字を指定すると、@F = split /{Fに指定した区切り文字}/と同じ動作になります。

      以下の例は、入力されたCSVを区切り文字で分解して、間にタブを挟んで出力する例です。

      $ more sample.csv 
      aaa,0001
      bbb,0002
      ccc,0003
      $ perl -aF, -nle 'print join "\t",@F' sample.csv 
      aaa	0001
      bbb	0002
      ccc	0003

    • -iオプションで入力された結果を入力元へ書き戻す

    • -iオプションは入力された内容を書き換えて、入力元へ書き戻す事が出来ます。

      $ more sample.txt
      aaa,001
      bbb,002
      ccc,003
      $ perl -i -ple 's/,/\t/g' sample.txt 
      $ more sample.txt
      aaa     001
      bbb     002
      ccc     003

      -iに引き続いて、拡張子を指定すると書き換え前のバックアップを取る事も出来ます。

      $ more sample.txt
      aaa,001
      bbb,002
      ccc,003
      $ perl -i.bak -ple 's/,/\t/g' sample.txt 
      $ more sample.txt
      aaa     001
      bbb     002
      ccc     003
      $ more sample.txt.bak 
      aaa,001
      bbb,002
      ccc,003


→Perl To The Peopleのインデックスページへ戻る

トラックバックURL

このエントリーのトラックバックURL:
http://ash.roova.jp/mt/mt-tb.cgi/109

コメントする