Home

技術系のメモと日々の雑感

Perl のワンライナーについての個人的なメモ

仕事で Perl のワンライナー(One Liner)を利用することがあって、基本的な振る舞いが分かってなかったせいで結構ハマってしまった。
で、個人的に調べた限りでは、サンプルはたくさん見付かるものの、自分がほしかった情報が書かれたサイトがなかったのでまとめておくことにした。
バージョンは v5.8.8 を想定。
自分用に書いているので結構適当だからご注意を。
間違い等に気付いたらコメントでツッコミを入れてもらえると嬉しい。


1.perl のコマンドラインオプション
perl -h の出力について日本語の情報が見当たらなかったので適当に訳して、 perldoc perlrun に書かれている内容も必要に応じて追加したもの。(ワンライナーとは直接関係ないオプションもある)

-0[octal]
specify record separator (¥0, if no argument)
レコードセパレータを8進数で指定(指定されなかったら ¥0)

-a
autosplit mode with -n or -p (splits $_ into @F)
-n や -p 指定時に $_ を @F に分割して代入する

-C[number/list]
enables the listed Unicode features
wide-character の処理(ユニコードの機能)を有効にする

-c
check syntax only (runs BEGIN and CHECK blocks)
シンタックスチェックのみ行う
ただし BEGIN と CHECK ブロックは実行する

-d[:debugger]
run program under debugger
指定されたモジュールの下でプログラムを実行する
デフォルトのモジュールは Perl デバッガ

-D[number/list]
set debugging flags (argument is a bit mask or alphabets)
デバッグフラグをセットする
引数はビットマスクまたはアルファベットで指定

-e program
one line of program (several -e's allowed, omit programfile)
1行だけのプログラムを指定する
複数回指定可

-f
don't do $sitelib/sitecustomize.pl at startup
起動時に「$sitelib/sitecustomize.pl」を実行しない

-F/pattern/
split() pattern for -a switch (//'s are optional)
-a オプション用の正規表現による分割パターンの指定
-FPATTERN、-F''、-F'//'、-F""、-F"//" のいずれでも指定可

-i[extension]
edit <> files in place (makes backup if extension supplied)
インプレースでファイルを編集する
拡張子を指定した場合はバックアップファイルを作成する

-Idirectory
specify @INC/#include directory (several -I's allowed)
@INC(Perl ライブラリ検索ディレクトリのリスト)の指定
複数回指定可

-l[octal]
enable line ending processing, specifies line terminator
改行文字の編集処理を有効にする(自動的に chomp を実行)
または改行文字を8進数で指定

-[mM][-]module
execute "use/no module..." before executing program
プログラム実行前に指定された Perl モジュール use する
module=... でインポートする項目の指定可
※このオプションのみシェバング(#!/usr/bin/perl)には指定不可

-n
assume "while (<>) { ... }" loop around program
入力ループに囲われているものとしてプログラムを実行する

-p
assume loop like -n but print line also, like sed
-n と同様にプログラムを処理
さらに結果を自動的に出力する(sed コマンドに似た動作)
-p と -n の両方が指定された場合は -p が優先される

-P
run program through C preprocessor before compilation
コンパイル前に C プリプロセッサを実行してからプログラムを実行
※使用は推奨されない(移植性に問題が出る?)

-s
enable rudimentary parsing for switches after programfile
プログラムファイルの後のオプションについて基本的な解析を行う

-S
look for programfile using PATH environment variable
環境変数 PATH を参照してプログラムファイルを探す

-t
enable tainting warnings
テイントモード(汚染検出モード)の警告を有効にする

-T
enable tainting checks
テイントモード(汚染検出モード)のチェックを有効にする

-u
dump core after parsing program
プログラムの解析後にコアダンプする

-U
allow unsafe operations
安全でない操作を許可する
※root でのディレクトリの unlink や setuid されたプログラムの実行

-v
print version, subversion (includes VERY IMPORTANT perl info)
バージョンとパッチレベルの表示(非常に重要な Perl 情報も含む)

-V[:variable]
print configuration summary (or a single Config.pm variable)
Perl の設定情報を表示(または指定された Config.pm の変数の表示)

-w
enable many useful warnings (RECOMMENDED)
多くの有用な警告を有効にする(推奨)

-W
enable all warnings
すべての警告を有効にする

-x[directory]
strip off text before #!perl line and perhaps cd to directory
#!perl より前の文を取り除く
指定されたディレクトリに移動してからプログラムを実行する

-X
disable all warnings
すべての警告を無効にする


2.ワンライナーのサンプル
とりあえず一刻も早く処理結果がほしいときのために典型的なワンライナーのサンプルを並べておく。
流用しやすいようにごく簡単なものばかりにしている。

■標準入力を編集

ls -l | perl -pe 's/ +/ /g'

■上と同じ処理を別の書き方で

ls -l | perl -ne 's/ +/ /g; print;'

■インプレースでファイルを編集

perl -i.bak -pe 's/^id:3/id:5/' /etc/inittab

■入力を自動的に分割

perl -F: -nae 'print "$F[0]¥n" if($F[2]>=500);' /etc/passwd

■モジュールの使用

perl -MLWP::Simple -e 'getprint "http://www.hoge.hoge.com/"';


3.ワンライナーに関する Tips
自分であれこれ調べたり試しているうちに分かったことなどをざっくりまとめておく。

■コマンドラインで指定したファイルの扱い
perldoc の説明によると次のような動きをするそうだ。

perl は指定されたファイルの1つ目をプログラム、2つ目以降を引数(データ)として扱う。
-e オプションが指定されず、ファイルが1つしか指定されてなかったらプログラムとみなす。
-e オプションが指定されていたら、プログラムの後に指定されたファイルをデータとみなす。
ファイルが1つも指定されてなかったらデータを標準入力から読み込む。
引数(データファイル)が複数指定されていて、途中で読み込めないファイルがあったら警告を表示して次のファイルの処理に移る。


■インプレース編集について(-i オプション)

perl -i.bak -ne 's/hoge/fuga/;' sample

として実行すると sample が空になるので変だなと思って perldoc を見てみると

It does this by renaming the input file, opening the output file by the original name, and selecting that output file as the default for print() statements.
【適当な訳】入力ファイル(引数で指定されたファイル)はリネームされる。オリジナルの名前で出力ファイルがオープンされ、そちらに print 文の結果が出力される。

とのこと。
なので -p を使うか

perl -i.bak -ne 's/hoge/fuga/; print;' sample

と書かないといけないんだね。

■改行の処理について(-l オプション)
-l は、ヘルプや perldoc の文章を見ただけでは気付きにくいんだけど、入力に対して chomp を実行するだけでなく、出力に自動で改行を付加する機能も持っている。

$ perl -le 'print "Hello"'
Hello
$

という感じ。
で、プログラムの中で改行が入っていたら判断するのかと思ったら

perl -le 'print "Hello¥n"'
Hello

$

こっちはひとつ余分に改行が出力されたので、出力側は無条件に改行を付けるようだ。
このオプションは -a とセットで使うと便利だね。

■オプションの解析方法の変更について(-s オプション)
-s は、例えば -xyz=5 と指定したときに変数 $xyz に 5 をセットするようにオプションの解析方法を変えるものらしいが、ワンライナーではあまり意味がなさそう。
普通に指定するとエラーになるので

perl -se 'print $xyz' -- -xyz=5

という感じで実行しないといけないんだけど、こんなことしなくても

perl -e '$xyz=5; print $xyz'

で済んでしまうからね。
どんな使い道があるのかな。
ちなみに = 以降を省略すると変数に 1 がセットされる。

■文を並べただけのプログラムファイルについて
ワンライナーの話からはちょっと外れるけど

perl -pe 's/ +/ /g;s/^ //;s/ ¥n$//;s/^¥n$//;' sample

といった感じでコマンドラインに複数の文をベタ書きしてしまうと、見にくくなるし、ちょっとした手直しがしにくくなるんで、こういうときは次のような文を並べただけのファイルを作って実行するといいかも。

s/ +/ /g;
s/^ //;
s/ ¥n$//;
s/^¥n$//;
print;

ループは -n オプションに任せてしまえば楽だね。

perl -n hoge.pl sample

hoge.pl の最後で print しているのは手直し等をしやすくするためで、もちろん -p を使っても問題ナシだ。

とりあえずこんなところかな。
また何か気付いたら追加しよっと。

この記事に対するトラックバック

この記事のトラックバックURL

-

管理人の承認後に表示されます

  • From: |
  • 2013/12/11(水) 11:57:24

-

管理人の承認後に表示されます

  • From: |
  • 2013/12/11(水) 03:45:19

-

管理人の承認後に表示されます

  • From: |
  • 2013/12/05(木) 12:41:45

-

管理人の承認後に表示されます

  • From: |
  • 2013/11/25(月) 04:14:00

-

管理人の承認後に表示されます

  • From: |
  • 2013/11/16(土) 03:10:41

-

管理人の承認後に表示されます

  • From: |
  • 2013/11/15(金) 16:12:48

-

管理人の承認後に表示されます

  • From: |
  • 2013/11/12(火) 16:10:19

-

管理人の承認後に表示されます

  • From: |
  • 2013/11/06(水) 17:14:33

-

管理人の承認後に表示されます

  • From: |
  • 2013/11/06(水) 10:24:33

-

管理人の承認後に表示されます

  • From: |
  • 2013/11/06(水) 07:50:56

-

管理人の承認後に表示されます

  • From: |
  • 2013/11/05(火) 11:33:09

-

管理人の承認後に表示されます

  • From: |
  • 2013/11/03(日) 02:27:36

-

管理人の承認後に表示されます

  • From: |
  • 2013/11/02(土) 22:18:31

-

管理人の承認後に表示されます

  • From: |
  • 2013/11/01(金) 00:10:47

-

管理人の承認後に表示されます

  • From: |
  • 2013/10/31(木) 05:15:55

-

管理人の承認後に表示されます

  • From: |
  • 2013/10/26(土) 18:26:24

-

管理人の承認後に表示されます

  • From: |
  • 2013/10/25(金) 00:15:32

-

管理人の承認後に表示されます

  • From: |
  • 2013/10/23(水) 14:43:26

-

管理人の承認後に表示されます

  • From: |
  • 2013/10/18(金) 12:05:19

-

管理人の承認後に表示されます

  • From: |
  • 2013/10/17(木) 18:34:46

-

管理人の承認後に表示されます

  • From: |
  • 2013/10/17(木) 17:19:00

-

管理人の承認後に表示されます

  • From: |
  • 2013/10/17(木) 15:58:09

-

管理人の承認後に表示されます

  • From: |
  • 2013/10/17(木) 10:42:36

-

管理人の承認後に表示されます

  • From: |
  • 2013/09/12(木) 16:07:01

-

管理人の承認後に表示されます

  • From: |
  • 2013/08/08(木) 12:54:45

-

管理人の承認後に表示されます

  • From: |
  • 2013/08/05(月) 21:28:03

-

管理人の承認後に表示されます

  • From: |
  • 2013/08/05(月) 20:02:51

-

管理人の承認後に表示されます

  • From: |
  • 2013/08/03(土) 06:20:13

-

管理人の承認後に表示されます

  • From: |
  • 2013/07/15(月) 03:53:02

-

管理人の承認後に表示されます

  • From: |
  • 2013/07/08(月) 16:07:35

-

管理人の承認後に表示されます

  • From: |
  • 2013/05/22(水) 18:12:52

-

管理人の承認後に表示されます

  • From: |
  • 2013/05/16(木) 16:18:36

-

管理人の承認後に表示されます

  • From: |
  • 2011/11/03(木) 11:36:10

-

管理人の承認後に表示されます

  • From: |
  • 2011/06/10(金) 09:31:05

この記事に対するコメント

承認待ちコメント

このコメントは管理者の承認待ちです

  • 投稿者: -
  • 2011/02/27 08:32:58
  • [編集]

この記事にコメントする

管理者にだけ表示を許可する