PerlのコードはPythonやRuby等の他のプログラミング言語より前提とする知識が必要に思います。特に変数が特徴的だったり、構文が特徴的だったり($_がよく利用されたり省略されたり)します。少し見てどういうコードなんだろうとよく思うので少しPerlについて調べてみようと思います。
何となく触れるようになればいい程度なので、あまり詳しくは調べませんが、少し公式ドキュメントを見たら、Perlのコードの意味が理解できればという気持ちで記事を書きます。
また、この記事で利用しているPerlのバージョンはv5.32.1になります。
コマンドとして利用
-eオプションを用いると引数の文字列をPerlのプログラムとして解釈して実行します。
1 2 |
$ perl -e 'print "Hello World\n"' Hello World |
-Eオプションを用いるとプラグマの'feature'で利用できる機能をすべてオンにして、-eオプションのように利用できます。
プラグマの'feature'は、既存のプログラムを壊さないようにPerlの新しい機能が追加された際のリスクを軽減する機能になります。
文字を表示する際はprint関数より末尾に改行を入れるsay関数が利用できるようになり、say関数は便利なので、-eオプションより良いかもしれません。
1 2 |
$ perl -E 'say "Hello World"' Hello World |
-nオプションを用いるとPerlをsed -nやawkのような繰り返し処理に利用できます。これは
1 2 3 |
while (<>) { ... # プログラムの処理 } |
のような処理を行います。ここでの<>演算子(ダイヤモンド演算子)はファイルから一行を読み込む演算子になります。
1 2 3 4 5 6 |
$ perl -ne '$line+=1; print "$line: $_"' data.txt 1: data1 2: data2 3: data3 4: data4 5: data5 |
未定義値はFALSEや空文字列や 数値の0として扱われます。変数$_は文脈によって様々な利用が行なわれるグローバル変数で、ここでは読み込んだ行を意味します。
-pオプションはsedのような繰り返し処理に利用できます。これは
1 2 3 4 5 |
while (<>) { ... # プログラムの処理 } continue { print or die "-p destination: $!\n"; } |
のような処理を行います。
1 2 3 4 5 6 7 |
$ perl -pe '$_="" if /data[135]/' data.txt data2 data4 $ perl -pe 's/([13])\n/$1 /' data.txt data1 data2 data3 data4 data5 |
上の例の2つ目の$1は、'()'でキャプチャしたものを表現します。
プログラムの作成と実行
Perlプログラムの拡張子は実行プログラムの場合は.plを用いて、モジュールの場合は.pmを用います。
プログラムの実行方法は
1 |
perl <ファイル名> |
のように実行する方法の他に、プログラムの1行目にシバン(#!のこと、shebang)を書き込み、実行権限を与えて、実行する方法があります。
1 2 3 4 5 |
$ cat <ファイル名> # ファイル内容の確認 #!/usr/bin/perl ~~~~プログラムの内容は省略~~~~ $ chmod u+x <ファイル名> # 実行権限の付与 $ ./<ファイル名> # スクリプトの実行 |
シバンはファイルの最初の行が'#!'で、その後にインタプリタ(perlやpython、bash等)を指定することで、シバンが書かれたスクリプトファイルはそのインタプリタの言語で記述して実行できるようになります。これはUnixのほとんどのバージョンで用いることができ、よく利用される実行メカニズムになります。
Perlプログラムを書く際に、シバンとして用いられるものとして、
1 |
#!/usr/bin/perl |
とPerlのインタプリタのパスを直接指定せずに
1 |
#!/usr/bin/env perl |
で、envコマンドを利用して、perlを実行する方法もあります。
組み込み変数
Perlの組み込み変数は$PROCESS_IDのような名前がついているものの他に、$$, $_のような記号を用いた組み込み変数が多くあります。
また一部、Perlの変数として$が使われていない変数もあります。詳しくは公式ドキュメントを確認してみてください(記事の下の方に参考としてリンクがあります)。
$_
$_(又は$ARG)は、入力を読み込むデフォルト値、パターンマッチングのみの文への出力値、特定の関数のデフォルトの引数(abs, chomp等の場合)や出力値(readline等の場合)のように多くの用途で利用されるグローバル変数になります。例えば、以下のペアは等価な文となります。
1 2 |
while (<>) {...} # while文の中で$_を利用するときに等価になります while (defined($_ = <>)) {...} |
1 2 |
/^Subject:/ $_ =~ /^Subject:/ |
1 2 |
tr/a-z/A-Z/ $_ =~ tr/a-z/A-Z/ |
1 2 |
chomp chomp($_) |
STDIN, STDOUT, STDERR, ARGV
STDIN, STDOUT, STDERR, ARGVはPerlで事前に予約されている特別なファイルハンドラになります。
それぞれ、
- STDINは標準入力
- STDOUTは標準出力
- STDERRは標準エラー出力
- ARGVは引数になっているファイル
になります。
簡単にARGVの変数を利用した例を紹介します。内容はそれぞれのファイルの内容を表示するものとなります。
1 2 3 4 5 6 7 |
$ echo 'file1' > file1.txt $ echo 'file2' > file2.txt $ echo 'file3' > file3.txt $ perl -e 'while(<ARGV>){print;}' file{1,2,3}.txt file1 file2 file3 |
また、'file{1,2,3}.txt'は、Bashのファイル名展開の機能で'file1.txt file2.txt file3.txt'と展開されます。
1 2 |
$ echo file{1,2,3}.txt file1.txt file2.txt file3.txt |
perlの関数と組み込み関数
perlの関数はリスト演算子(list operators)と名前付き単項演算子(named unary operators)として扱うこともできます。
リスト演算子は複数の引数を取ることができます。
名前付き単項演算子は複数の引数を取ることができません。つまり、引数は0個または1個になります。
補足として、コンマ(,)の解釈について、リスト演算子は引数のリストになりますが、名前付き単項演算子は引数の終了を意味します。
1 2 3 4 |
$ perl -e 'print 3, 2, sort 11, 10; print "\n"' 321011 $ perl -e 'print 3, 2, hex f, 10; print "\n"' 321510 |
1つ目のリスト演算子(sortの例)を利用したprint文の引数の解釈は(3), (2), (sort 11, 10)になりますが、
2つ目の名前付き単項演算子(hexの例)を利用したprint文の引数の解釈は(3), (2), (hex f), (10)になります。
括弧を用いれば、当然ですが関数にもなります。ただし、関数と括弧の間のスペースは無視されます。
1 2 3 4 |
$ perl -e 'print(1+2); print "\n"' 3 $ perl -e 'print (1+2); print "\n"' 3 |
関数と括弧の間のスペースが無視されることは面倒な解釈をもたらす可能性があります。
1 2 3 4 5 6 |
$ perl -e 'print (1+2) + 4; print "\n"' 3 $ perl -e 'print +(1+2) + 4; print "\n"' 7 $ perl -e 'print ((1+2) + 4); print "\n"' 7 |
数値の結果として7を表示したいとすると、
1つ目はprintを演算子のように扱おうとして、関数になり意図しない結果になってしまった例になります。
2つ目はprintを演算子として利用した例で、'+'をつけることで関数として解釈されないようにした例になります。
3つ目はprintを関数として利用した例になります。
Perlの組み込み関数はUnixシステムコールにアクセスするものやCのライブラリ関数のようなものが多くあります。
例えば、ホスト名をIPアドレスに変換するコマンドはCのライブラリ関数を使うように以下のように記述できます。
1 2 |
$ perl -MSocket -e '$packedip = gethostbyname("www.perl.org"); print inet_ntoa($packedip),"\n"' 151.101.194.132 |
gethostbyname関数はPerlの組み込み関数、inet_ntoaがSocketモジュールの関数になります。
Socketモジュールについては
Socket - networking constants and support functions - Perldoc Browserを参照してください。
参考
perlの公式サイト
The Perl Programming Language - www.perl.org
perlのドキュメントを日本語に翻訳しているサイト
perldoc.jp
perlのコマンドラインオプションについて
perlrun - how to execute the Perl interpreter - Perldoc Browser
Perlの組み込み変数について
perlvar - Perl predefined variables - Perldoc Browser
組み込み関数のリストについて
perlfunc - Perl builtin functions - Perldoc Browser