1月17日木曜日: 実行とオプション
実行にあたって、Perl は指定されたスクリプトを以下に示す場所で探します:
コマンドライン上で `-e' スイッチで指定された行。
コマンドライン上で最初のファイル名として示されたファイルの中。(#! 記法をサポートしているシステムでは、このようにしてインタプリタを呼び出します。)
標準入力から非明示に渡される。ファイル名を示す引数が無い場合にのみうまくいきます。STDIN からのスクリプトに引数を渡すには、スクリプト名として明示的に "-" を指定しなくてはなりません、
2 番目、3 番目の方法では、`-x' スイッチを指定した場合を除いて、Perl は入力ファイルを最初から解析し始めます。`-x' スイッチを指定した場合には、まず、最初に #! と "perl" という文字列を含む行を探し、そこから解析を始めます。これは、大きなテキストにスクリプトを埋め込んで、実行するようなときに便利です。(この場合、スクリプトの終わりは、トークン __END__ を使って示すとよいでしょう。)
Perl 5 からは、#! を含む行のスイッチが必ず解析されるようになりました。つまり、#! の行で引数が一つしか許されない、あるいはもっと悪く、#! の行が認識されないといったシステムで運用している場合にも、`-x' でスクリプトの開始位置を見つけた場合を含め、どのように Perl が起動されたかによらず、一貫したスイッチの動作を期待できるようになっています。
多くの OS で、カーネルによる #! 行の解釈が、エラーなしに 32文字で打ち切られてしまいますので、あるスイッチはコマンドラインに渡され、あるスイッチは渡されないといったことが起こります。注意しないと、文字が続かない "-" だけが渡されるといったことも起こり得ます。すべてのスイッチが、32 文字境界の前か後ろかを確かめたいことでしょう。多くのスイッチは、余分に処理されても問題ありませんが、完全なスイッチの代わりに - が入っていた場合には、スクリプトの代わりに、標準入力を Perl に実行させることになってしまいます。 `-I' スイッチが中途半端になった場合にもおかしな結果となり得ます。
#! スイッチの解析は、行内で "perl" が示された位置から始まります。とりわけ "-*" と "- " という文字の並びは無視されますので、
#!/bin/sh -- # -*- perl -*- -p
eval 'exec perl $0 -S ${1+"$@"}'
if 0;
のように書けば、Perl に `-p' スイッチを渡すことができます。
#! 行に "perl" という語が含まれていなければ、#! の後に指定されたプログラムが Perl インタプリタの代わりに実行されます。これは少し変わっていますが、 #! が行なえないマシンを使っている方には有効でしょう。プログラムに対して使っている SHELL が /usr/bin/perl だと言っておけば、Perl が正しいインタプリタを起動してくれるからです。
スクリプトの場所が特定できたなら、Perl はスクリプト全体を内部形式にコンパイルし始めます。コンパイルエラーが見つかった時には、スクリプトの実行は行なわれません。(これは、構文エラーがある場合にも、途中まで実行される可能性のある、典型的なシェルのスクリプトと異なる点です。)
スクリプトが構文的に正しければ、実行されることになります。スクリプトが、 exit() 演算子にも die() 演算子にも当たらないで最後まで到達すると、正常に完了したことを示すために、暗黙の exit(0) が行なわれます。
1 文字のスイッチは、次に続くスイッチがあれば、それとつなげることができます。
#!/usr/bin/perl -spi.bak # -s -p -i.bak と同じ
コマンドライン上で `-e' スイッチで指定された行。
コマンドライン上で最初のファイル名として示されたファイルの中。(#! 記法をサポートしているシステムでは、このようにしてインタプリタを呼び出します。)
標準入力から非明示に渡される。ファイル名を示す引数が無い場合にのみうまくいきます。STDIN からのスクリプトに引数を渡すには、スクリプト名として明示的に "-" を指定しなくてはなりません、
2 番目、3 番目の方法では、`-x' スイッチを指定した場合を除いて、Perl は入力ファイルを最初から解析し始めます。`-x' スイッチを指定した場合には、まず、最初に #! と "perl" という文字列を含む行を探し、そこから解析を始めます。これは、大きなテキストにスクリプトを埋め込んで、実行するようなときに便利です。(この場合、スクリプトの終わりは、トークン __END__ を使って示すとよいでしょう。)
Perl 5 からは、#! を含む行のスイッチが必ず解析されるようになりました。つまり、#! の行で引数が一つしか許されない、あるいはもっと悪く、#! の行が認識されないといったシステムで運用している場合にも、`-x' でスクリプトの開始位置を見つけた場合を含め、どのように Perl が起動されたかによらず、一貫したスイッチの動作を期待できるようになっています。
多くの OS で、カーネルによる #! 行の解釈が、エラーなしに 32文字で打ち切られてしまいますので、あるスイッチはコマンドラインに渡され、あるスイッチは渡されないといったことが起こります。注意しないと、文字が続かない "-" だけが渡されるといったことも起こり得ます。すべてのスイッチが、32 文字境界の前か後ろかを確かめたいことでしょう。多くのスイッチは、余分に処理されても問題ありませんが、完全なスイッチの代わりに - が入っていた場合には、スクリプトの代わりに、標準入力を Perl に実行させることになってしまいます。 `-I' スイッチが中途半端になった場合にもおかしな結果となり得ます。
#! スイッチの解析は、行内で "perl" が示された位置から始まります。とりわけ "-*" と "- " という文字の並びは無視されますので、
#!/bin/sh -- # -*- perl -*- -p
eval 'exec perl $0 -S ${1+"$@"}'
if 0;
のように書けば、Perl に `-p' スイッチを渡すことができます。
#! 行に "perl" という語が含まれていなければ、#! の後に指定されたプログラムが Perl インタプリタの代わりに実行されます。これは少し変わっていますが、 #! が行なえないマシンを使っている方には有効でしょう。プログラムに対して使っている SHELL が /usr/bin/perl だと言っておけば、Perl が正しいインタプリタを起動してくれるからです。
スクリプトの場所が特定できたなら、Perl はスクリプト全体を内部形式にコンパイルし始めます。コンパイルエラーが見つかった時には、スクリプトの実行は行なわれません。(これは、構文エラーがある場合にも、途中まで実行される可能性のある、典型的なシェルのスクリプトと異なる点です。)
スクリプトが構文的に正しければ、実行されることになります。スクリプトが、 exit() 演算子にも die() 演算子にも当たらないで最後まで到達すると、正常に完了したことを示すために、暗黙の exit(0) が行なわれます。
1 文字のスイッチは、次に続くスイッチがあれば、それとつなげることができます。
#!/usr/bin/perl -spi.bak # -s -p -i.bak と同じ
1月17日木曜日: Version 8 正規表現
万が一、みなさんが「正規の」Version 8 正規表現ルーティンを知らなかった場合のために、これまでに書いていないパターンマッチの規則を示します。
ある 1 文字は、その文字がこの節かこれまでに示した「メタ文字」でない場合には、その文字自身にマッチします。通常はメタ文字として働く文字も、前に "\" を付けることで、文字通りに解釈されるようにすることができます。(たとえば、"\." は任意の 1 文字ではなく、"." という文字にマッチします。)文字の並びは、対象の文字列の中の同じ文字の並びにマッチしますから、blurfl というパターンは、対象となる文字列の "blurfl" にマッチします。
文字のリストを [] で囲って、そのリストのいずれかの文字にマッチする、文字クラスを指定することができます。"[" に続く最初の文字が "^" であれば、その文字クラスは、リストに無い文字にマッチするようになります。リストの中では、"-" が範囲を示すのに使われ、a-z は "a" から "z" までのすべての文字を表わします。
C で使われているのと非常によく似たメタ文字構文を使って、文字を指定することができます。"\n" が改行、"\t" がタブ、"\r"が復帰、"\f" が改ページといった具合です。さらに一般的には、nnn を 8 進数の数字として、\nnn は ASCII 値が nnn の文字にマッチします。同様に、nn を 16 進数の数字として、\xnn はASCII 値が nn の文字にマッチします。\cx という式は、ASCII 文字 control-x にマッチします。最後に、メタ文字 "." は (/s を使っているときを除いて) "\n" を除くどんな文字にもマッチします。
"|" で区切ることで、パターンの選択肢を示すことができますから、 fee|fie|foe は、対象の文字列の "fee" か "fie" か "foe" のいずれかにマッチします (f(e|i|o)e と同じ)。最初の選択肢には、最後の区切文字 ("(" か "[" かパターンの始め) の後から最初の"|" の前までが含まれ、最後の選択肢には、最後の "|" の後から次のパターンの区切文字の前までが含まれます。この事から、最初と最後をはっきりさせるために、選択肢を括弧に入れることがよく行なわれます。(fee|fie|foe) というパターンは、[fee|fie|foe] というパターンとは違うことに注意してください。前者が対象文字列の "fee" か "fie" か "foe" にマッチするのに対して、後者は [fee] か [fie] か [foe] のいずれかの文字クラスにマッチするものにマッチします (つまり、文字クラス [feio] です)。
パターンではあとで参照するために、括弧で括ってサブパターンを指定でき、そのパターンの中で n 番目のサブパターンを \n というメタ文字で参照することができます。サブパターンは、左から右に向かって、開き括弧に対して番号がつけられます。後方参照は、サブパターンが調べられる文字列中で、実際にマッチしたものにマッチするのであって、そのサブパターン規則そのものにマッチするのではありません。ですから、([0|0x])\d*\s\1\d* というパターンは、"0x1234 0x4321" にマッチしますが、"0x1234 01234" にはマッチしません。たとえ [0|0x] という規則が 2 番目の数字の前の 0 にマッチすることができるとしても、サブパターン 1 は、"0x" にマッチしたものだからです。
ある 1 文字は、その文字がこの節かこれまでに示した「メタ文字」でない場合には、その文字自身にマッチします。通常はメタ文字として働く文字も、前に "\" を付けることで、文字通りに解釈されるようにすることができます。(たとえば、"\." は任意の 1 文字ではなく、"." という文字にマッチします。)文字の並びは、対象の文字列の中の同じ文字の並びにマッチしますから、blurfl というパターンは、対象となる文字列の "blurfl" にマッチします。
文字のリストを [] で囲って、そのリストのいずれかの文字にマッチする、文字クラスを指定することができます。"[" に続く最初の文字が "^" であれば、その文字クラスは、リストに無い文字にマッチするようになります。リストの中では、"-" が範囲を示すのに使われ、a-z は "a" から "z" までのすべての文字を表わします。
C で使われているのと非常によく似たメタ文字構文を使って、文字を指定することができます。"\n" が改行、"\t" がタブ、"\r"が復帰、"\f" が改ページといった具合です。さらに一般的には、nnn を 8 進数の数字として、\nnn は ASCII 値が nnn の文字にマッチします。同様に、nn を 16 進数の数字として、\xnn はASCII 値が nn の文字にマッチします。\cx という式は、ASCII 文字 control-x にマッチします。最後に、メタ文字 "." は (/s を使っているときを除いて) "\n" を除くどんな文字にもマッチします。
"|" で区切ることで、パターンの選択肢を示すことができますから、 fee|fie|foe は、対象の文字列の "fee" か "fie" か "foe" のいずれかにマッチします (f(e|i|o)e と同じ)。最初の選択肢には、最後の区切文字 ("(" か "[" かパターンの始め) の後から最初の"|" の前までが含まれ、最後の選択肢には、最後の "|" の後から次のパターンの区切文字の前までが含まれます。この事から、最初と最後をはっきりさせるために、選択肢を括弧に入れることがよく行なわれます。(fee|fie|foe) というパターンは、[fee|fie|foe] というパターンとは違うことに注意してください。前者が対象文字列の "fee" か "fie" か "foe" にマッチするのに対して、後者は [fee] か [fie] か [foe] のいずれかの文字クラスにマッチするものにマッチします (つまり、文字クラス [feio] です)。
パターンではあとで参照するために、括弧で括ってサブパターンを指定でき、そのパターンの中で n 番目のサブパターンを \n というメタ文字で参照することができます。サブパターンは、左から右に向かって、開き括弧に対して番号がつけられます。後方参照は、サブパターンが調べられる文字列中で、実際にマッチしたものにマッチするのであって、そのサブパターン規則そのものにマッチするのではありません。ですから、([0|0x])\d*\s\1\d* というパターンは、"0x1234 0x4321" にマッチしますが、"0x1234 01234" にはマッチしません。たとえ [0|0x] という規則が 2 番目の数字の前の 0 にマッチすることができるとしても、サブパターン 1 は、"0x" にマッチしたものだからです。
1月16日水曜日: 正規表現の書き方
パターンマッチで用いるパターンは、Version 8 regexp ルーティンで提供されているような正規表現です。(実際、使用しているルーティンは、Henry Spencer が書き直した再配布可能な V8 のルーティンを元にしています。)詳しくは、「See section Version 8 正規表現,」の節を参照してください。
特に、以下のメタ文字は、標準的な egrep(1) と同様の意味を表わします:
\ 次のメタ文字をクォートする
^ 行の最初にマッチする
. (改行以外の) すべての文字にマッチする
$ 行の終わりにマッチする
| 選択
() グループ化
[] 文字クラス
デフォルトでは、文字 "^" は文字列の最初にだけ、文字 "$" は最後 (もしくは、最後の改行の前) にだけマッチすることが保証されており、Perl は文字列には 1 行だけが含まれていると仮定して、最適化を行ないます。文字列の中に埋め込まれた改行は、"^" や"$" はマッチしません。しかし、文字列を複数行のバッファとして扱い、"^" はすべての改行のあとにマッチし、"$" はすべての改行の前にマッチするようにしたい場合もあるでしょう。少しばかり負荷がかかりますが、パターンマッチ演算子に /m 修飾子を付けると、そのようにすることができるようになります。(昔のプログラムでは $* を設定することでこれを行なっていましたが、Perl 5 でこれを行なうことは芳しくありません。)
複数行の置換を容易にするため、/s 修飾子を使わない限り、文字 "." は改行文字にマッチしません。この /s 修飾子は、文字列がたとえ複数行であっても単一行であるかのように扱うよう Perl に指示するものです。/s 修飾子は、他のモジュールで $* を設定するような (よくない) 過去のコードを持ってきたような場合にも、その $* の設定を無効にします。
次のような標準の数量子が認識されます:
* 0 回以上にマッチ
+ 1 回以上にマッチ
? 1 回または 0 回にマッチ
{n} ちょうど n 回にマッチ
{n,} n 回以上にマッチ
{n,m} n 回以上 m 回以下にマッチ
(中括弧が他の文脈であらわれた場合には、通常の文字として扱われます。) "*" 修飾子は {0,}、"+" は {1,}、"?" は {0,1} と等価なものとして扱われます。n や m の大きさに制限はありませんが、大きな数はそれだけメモリを消費します。
デフォルトでは、数量子を付けたサブパターンは、「最長一致」となり、残りのパターンがマッチしなくならない範囲で、できる限り多くのものにマッチするようになっています。つまり、標準の数量子は、すべて「最長一致」で、(適切な開始位置を与えると) パターンが失敗しない範囲で可能な限り長い範囲にマッチします。もし、最短の範囲でマッチさせたいのであれば、数量子の後に "?" を付けて指定します。この場合、「最短一致」となるだけで、意味するところは変わりありません:
*? 0 回以上にマッチ
+? 1 回以上にマッチ
?? 1 回または 0 回にマッチ
{n}? ちょうど n 回にマッチ
{n,}? n 回以上にマッチ
{n,m}? n 回以上 m 回以下にマッチ
パターンはダブルクォート文字列として処理されますから、
\t タブ
\n 改行
\r 復帰
\f 改ページ
\v 垂直タブ (それが何であっても)
(訳注: これは使えないように見える)
\a アラーム (ベル)
\e エスケープ
\033 8 進数で表した文字
\x1b 16 進数で表した文字
\c[ コントロール文字
\l 次の文字を小文字にする
\u 次の文字を大文字にする
\L \E まで小文字にする
\U \E まで大文字にする
\E 変更の終わり
\Q \E まで正規表現のメタ文字をクォートする
も使用できます。さらに、Perl では以下のものが定義されています:
\w 「単語」の構成文字 (英数字と "_") にマッチ
\W 単語の構成文字以外にマッチ
\s 空白文字にマッチ
\S 空白文字以外にマッチ
\d 数字にマッチ
\D 数字以外にマッチ
\w は 1 字の英数字にマッチするのであって、単語全体にマッチするのではないことに注意してください。単語全体にマッチさせるためには \w+ とする必要があります。\w, \W, \s, \S, \d, \Dは文字クラス内 (で範囲を指定する両端の文字以外の場所) でも使うことができます。
Perl では以下の長さのない、位置指定子を定義しています:
\b 単語の境界にマッチ
\B 単語の境界以外にマッチ
\A 文字列の最初にのみマッチ
\Z 文字列の最後にのみマッチ
\G 前回の m//g が終わったところにのみマッチ
単語の境界 (\b) は \w で定義される文字と \W で定義される文字の間というように定義されます (順番はどちらが先でもよい)。文字列の最初と最後には \W に含まれる仮想的な文字があるものとして扱われます。(文字クラスの中では \b は単語境界ではなく、バックスペースを表わします。)\A と \Z は /m 修飾子が用いられた場合にも 1 か所でしかマッチしないことを除いて "^" と "$"と同じ事になります。"^" と "$" は内部的な行の境界にもマッチします。
括弧括り ( ... ) の形式を用いている場合には、\<数字> がその括られている「数字」番目の部分文字列にマッチします。(パターンの外では、数字の前の "\" の代わりに "$" を使います。) $<数字> (と $`, $&, $') のスコープは、 BLOCK や eval 文字列の終わりや、次の部分式を使ったパターンマッチまでとなります。サブパターンとして記録せずに、括弧で括ってサブパターンを区切りたい (たとえば、選択肢をまとめる) 場合、"(" の後に "?" を続けます。\<数字> の記法は、そのパターンの外で使える場合もあるかもしれませんが、これに頼ってはなりません。括弧は、好きなだけ使ってかまいません。10 個以上の部分文字列は、$10,$11 などで参照することができます。そのパターンの中では、後方参照の前に最低限、参照している番号の数だけの開き括弧があれば、\10, \11 などで参照できます。その番号の数だけの開き括弧が無い場合には、(以前のバージョンとの互換性のために) \10 は、\010 (バックスペース)、\11 は \011 (タブ) といった意味になります。(\1 から \9 は、常に後方参照を意味します。)
$+ は、最後の括弧対にマッチしたものを返します。$& は、マッチした文字列全体を返します。(以前は、$0 がこの意味に使われましたが、現在は使えません。) $` は、マッチした文字列の前にあったものを返します。$' は、マッチした文字列の後にあったものを返します。例:
s/^([^ ]*) *([^ ]*)/$2 $1/; # 最初の 2 語を入替える
if (/Time: (..):(..):(..)/) {
$hours = $1;
$minutes = $2;
$seconds = $3;
}
Perl におけるすべてのバックスラッシュ付きのメタ文字が、\b,\w, \n といった英数字であることにお気付きかもしれません。他のいくつかの正規表現言語とは違って、英数字以外にバックスラッシュ付きの記号はありません。つまり、 \\, \(, \), \<, \>,\{, \} といったものはすべて、メタ文字ではなく、リテラル文字として解釈されます。このことによって、パターンとして使いたい文字列に、メタ文字と解釈される文字が含まれている可能性があるときに、たやすくクォートすることができるようになっています。単に英数字以外の文字を、すべてクォートすればよいのです:
$pattern =~ s/(\W)/\\$1/g;
同じことを行なうために、組み込みの関数 quotemeta() を使うこともできます。マッチ演算子の中でより簡単にメタ文字をクォートするには、
/$unquoted\Q$quoted\E$unquoted/
とすればよいでしょう。
Perl 5 では、正規表現に一貫した拡張構文を定義しています。構文は、括弧のペアの中に、最初の文字としてクエスチョンマークを置いたものとなっています (これは、Perl 4 では構文エラーです)。クエスチョンマークに続く文字で、拡張の機能のどれを使うのかを示します。いくつかの拡張が、既にサポートされています:
(?#text)
コメント。Text は無視されます。
(?:regexp)
これは、"()" と同じようにグループ化を行ないますが、"()" のように後方参照を生成しません。つまり
split(/\b(?:a|b|c)\b/)
は、
split(/\b(a|b|c)\b/)
と似ていますが、余分なフィールドを作りません。
(?=regexp)
長さの無い、前方参照位置指定子。たとえば、/\w+(?=\t)/ は、後ろにタブが続く単語にマッチしますが、そのタブは $& には含まれません。
(?!regexp)
長さの無い、前方参照否定位置指定子。たとえば、/foo(?!bar)/ は、後ろに "bar" が続かない "foo" にマッチします。前方参照と後方参照は、同じではないことに注意してください。この構文を後方を参照するために使うことはできません。/(?!foo)bar/ では、"foo" 以外のものに続く "bar" を見つけるものではありません。(?!foo) は次にくるものが "foo" でないとだけ言っているからで、次が "bar" であれば、当然"foo" ではありませんから、"foobar" がマッチします。先の目的のためには、/(?!foo)...bar/ のように書かなくてはならないでしょう。「ように」といったのは、"bar" の前に 3 文字無い場合もあるだろうからです。これもカバーするには、/(?:(?!foo)...|^..?)bar/ というように書けるでしょう。単に:
if (/foo/ && $` =~ /bar$/)
と書いた方が簡単なこともあります。 (訳注: これは if(/bar(?=foo)/) かな。($' を除く))
(?imsx)
パターンマッチ修飾子の埋め込み。これは、パターンが、どこかの表に示され、そのうちのいくつかは大文字小文字を区別せず、いくつかは区別するといった場合に便利です。区別するものでは、単にパターンの先頭に (?i) を付け加えればよいのです。たとえば:
$pattern = "foobar";
if ( /$pattern/i )
# パターンに埋め込めば、より柔軟:
$pattern = "(?i)foobar";
if ( /$pattern/ )
この構文や新しい最短一致の構文にクエスチョンマークを選らんだのは、1) 以前の正規表現においてクエスチョンマークが使われることが少なかったこと、2) これを見つけた人は「疑問」に思ってなにが起こるのかを考えるべきだということによります。これこそ、心理学 ...
特に、以下のメタ文字は、標準的な egrep(1) と同様の意味を表わします:
\ 次のメタ文字をクォートする
^ 行の最初にマッチする
. (改行以外の) すべての文字にマッチする
$ 行の終わりにマッチする
| 選択
() グループ化
[] 文字クラス
デフォルトでは、文字 "^" は文字列の最初にだけ、文字 "$" は最後 (もしくは、最後の改行の前) にだけマッチすることが保証されており、Perl は文字列には 1 行だけが含まれていると仮定して、最適化を行ないます。文字列の中に埋め込まれた改行は、"^" や"$" はマッチしません。しかし、文字列を複数行のバッファとして扱い、"^" はすべての改行のあとにマッチし、"$" はすべての改行の前にマッチするようにしたい場合もあるでしょう。少しばかり負荷がかかりますが、パターンマッチ演算子に /m 修飾子を付けると、そのようにすることができるようになります。(昔のプログラムでは $* を設定することでこれを行なっていましたが、Perl 5 でこれを行なうことは芳しくありません。)
複数行の置換を容易にするため、/s 修飾子を使わない限り、文字 "." は改行文字にマッチしません。この /s 修飾子は、文字列がたとえ複数行であっても単一行であるかのように扱うよう Perl に指示するものです。/s 修飾子は、他のモジュールで $* を設定するような (よくない) 過去のコードを持ってきたような場合にも、その $* の設定を無効にします。
次のような標準の数量子が認識されます:
* 0 回以上にマッチ
+ 1 回以上にマッチ
? 1 回または 0 回にマッチ
{n} ちょうど n 回にマッチ
{n,} n 回以上にマッチ
{n,m} n 回以上 m 回以下にマッチ
(中括弧が他の文脈であらわれた場合には、通常の文字として扱われます。) "*" 修飾子は {0,}、"+" は {1,}、"?" は {0,1} と等価なものとして扱われます。n や m の大きさに制限はありませんが、大きな数はそれだけメモリを消費します。
デフォルトでは、数量子を付けたサブパターンは、「最長一致」となり、残りのパターンがマッチしなくならない範囲で、できる限り多くのものにマッチするようになっています。つまり、標準の数量子は、すべて「最長一致」で、(適切な開始位置を与えると) パターンが失敗しない範囲で可能な限り長い範囲にマッチします。もし、最短の範囲でマッチさせたいのであれば、数量子の後に "?" を付けて指定します。この場合、「最短一致」となるだけで、意味するところは変わりありません:
*? 0 回以上にマッチ
+? 1 回以上にマッチ
?? 1 回または 0 回にマッチ
{n}? ちょうど n 回にマッチ
{n,}? n 回以上にマッチ
{n,m}? n 回以上 m 回以下にマッチ
パターンはダブルクォート文字列として処理されますから、
\t タブ
\n 改行
\r 復帰
\f 改ページ
\v 垂直タブ (それが何であっても)
(訳注: これは使えないように見える)
\a アラーム (ベル)
\e エスケープ
\033 8 進数で表した文字
\x1b 16 進数で表した文字
\c[ コントロール文字
\l 次の文字を小文字にする
\u 次の文字を大文字にする
\L \E まで小文字にする
\U \E まで大文字にする
\E 変更の終わり
\Q \E まで正規表現のメタ文字をクォートする
も使用できます。さらに、Perl では以下のものが定義されています:
\w 「単語」の構成文字 (英数字と "_") にマッチ
\W 単語の構成文字以外にマッチ
\s 空白文字にマッチ
\S 空白文字以外にマッチ
\d 数字にマッチ
\D 数字以外にマッチ
\w は 1 字の英数字にマッチするのであって、単語全体にマッチするのではないことに注意してください。単語全体にマッチさせるためには \w+ とする必要があります。\w, \W, \s, \S, \d, \Dは文字クラス内 (で範囲を指定する両端の文字以外の場所) でも使うことができます。
Perl では以下の長さのない、位置指定子を定義しています:
\b 単語の境界にマッチ
\B 単語の境界以外にマッチ
\A 文字列の最初にのみマッチ
\Z 文字列の最後にのみマッチ
\G 前回の m//g が終わったところにのみマッチ
単語の境界 (\b) は \w で定義される文字と \W で定義される文字の間というように定義されます (順番はどちらが先でもよい)。文字列の最初と最後には \W に含まれる仮想的な文字があるものとして扱われます。(文字クラスの中では \b は単語境界ではなく、バックスペースを表わします。)\A と \Z は /m 修飾子が用いられた場合にも 1 か所でしかマッチしないことを除いて "^" と "$"と同じ事になります。"^" と "$" は内部的な行の境界にもマッチします。
括弧括り ( ... ) の形式を用いている場合には、\<数字> がその括られている「数字」番目の部分文字列にマッチします。(パターンの外では、数字の前の "\" の代わりに "$" を使います。) $<数字> (と $`, $&, $') のスコープは、 BLOCK や eval 文字列の終わりや、次の部分式を使ったパターンマッチまでとなります。サブパターンとして記録せずに、括弧で括ってサブパターンを区切りたい (たとえば、選択肢をまとめる) 場合、"(" の後に "?" を続けます。\<数字> の記法は、そのパターンの外で使える場合もあるかもしれませんが、これに頼ってはなりません。括弧は、好きなだけ使ってかまいません。10 個以上の部分文字列は、$10,$11 などで参照することができます。そのパターンの中では、後方参照の前に最低限、参照している番号の数だけの開き括弧があれば、\10, \11 などで参照できます。その番号の数だけの開き括弧が無い場合には、(以前のバージョンとの互換性のために) \10 は、\010 (バックスペース)、\11 は \011 (タブ) といった意味になります。(\1 から \9 は、常に後方参照を意味します。)
$+ は、最後の括弧対にマッチしたものを返します。$& は、マッチした文字列全体を返します。(以前は、$0 がこの意味に使われましたが、現在は使えません。) $` は、マッチした文字列の前にあったものを返します。$' は、マッチした文字列の後にあったものを返します。例:
s/^([^ ]*) *([^ ]*)/$2 $1/; # 最初の 2 語を入替える
if (/Time: (..):(..):(..)/) {
$hours = $1;
$minutes = $2;
$seconds = $3;
}
Perl におけるすべてのバックスラッシュ付きのメタ文字が、\b,\w, \n といった英数字であることにお気付きかもしれません。他のいくつかの正規表現言語とは違って、英数字以外にバックスラッシュ付きの記号はありません。つまり、 \\, \(, \), \<, \>,\{, \} といったものはすべて、メタ文字ではなく、リテラル文字として解釈されます。このことによって、パターンとして使いたい文字列に、メタ文字と解釈される文字が含まれている可能性があるときに、たやすくクォートすることができるようになっています。単に英数字以外の文字を、すべてクォートすればよいのです:
$pattern =~ s/(\W)/\\$1/g;
同じことを行なうために、組み込みの関数 quotemeta() を使うこともできます。マッチ演算子の中でより簡単にメタ文字をクォートするには、
/$unquoted\Q$quoted\E$unquoted/
とすればよいでしょう。
Perl 5 では、正規表現に一貫した拡張構文を定義しています。構文は、括弧のペアの中に、最初の文字としてクエスチョンマークを置いたものとなっています (これは、Perl 4 では構文エラーです)。クエスチョンマークに続く文字で、拡張の機能のどれを使うのかを示します。いくつかの拡張が、既にサポートされています:
(?#text)
コメント。Text は無視されます。
(?:regexp)
これは、"()" と同じようにグループ化を行ないますが、"()" のように後方参照を生成しません。つまり
split(/\b(?:a|b|c)\b/)
は、
split(/\b(a|b|c)\b/)
と似ていますが、余分なフィールドを作りません。
(?=regexp)
長さの無い、前方参照位置指定子。たとえば、/\w+(?=\t)/ は、後ろにタブが続く単語にマッチしますが、そのタブは $& には含まれません。
(?!regexp)
長さの無い、前方参照否定位置指定子。たとえば、/foo(?!bar)/ は、後ろに "bar" が続かない "foo" にマッチします。前方参照と後方参照は、同じではないことに注意してください。この構文を後方を参照するために使うことはできません。/(?!foo)bar/ では、"foo" 以外のものに続く "bar" を見つけるものではありません。(?!foo) は次にくるものが "foo" でないとだけ言っているからで、次が "bar" であれば、当然"foo" ではありませんから、"foobar" がマッチします。先の目的のためには、/(?!foo)...bar/ のように書かなくてはならないでしょう。「ように」といったのは、"bar" の前に 3 文字無い場合もあるだろうからです。これもカバーするには、/(?:(?!foo)...|^..?)bar/ というように書けるでしょう。単に:
if (/foo/ && $` =~ /bar$/)
と書いた方が簡単なこともあります。 (訳注: これは if(/bar(?=foo)/) かな。($' を除く))
(?imsx)
パターンマッチ修飾子の埋め込み。これは、パターンが、どこかの表に示され、そのうちのいくつかは大文字小文字を区別せず、いくつかは区別するといった場合に便利です。区別するものでは、単にパターンの先頭に (?i) を付け加えればよいのです。たとえば:
$pattern = "foobar";
if ( /$pattern/i )
# パターンに埋め込めば、より柔軟:
$pattern = "(?i)foobar";
if ( /$pattern/ )
この構文や新しい最短一致の構文にクエスチョンマークを選らんだのは、1) 以前の正規表現においてクエスチョンマークが使われることが少なかったこと、2) これを見つけた人は「疑問」に思ってなにが起こるのかを考えるべきだということによります。これこそ、心理学 ...
1月16日水曜日: 正規表現
マッチ演算子においてどのように正規表現を使うかについての説明は、 See section 演算子と優先順位,の m// や s/// を参照してください。マッチ演算子は、いくつかの修飾子をとり、中の正規表現の解釈の仕方を変更することができます。修飾子には、
i 大文字小文字の区別をしないパターンマッチを行なう。
m 文字列を複数行として扱う。
s 文字列を単一行として扱う。
x 拡張正規表現を使用する。
があります。これらは通常、使用する区切り文字にスラッシュ以外のものを使うときでも、「/x 修飾子」のように書かれます。実際には、これらの修飾子は、 (?...) という新しい形式で正規表現の中に埋め込んでしまうこともできます。これについては、あとで述べます。
/x 修飾子について、もう少し説明しておきましょう。これは、正規表現のパーザに、バックスラッシュでエスケープされている空白、文字クラス内で使われている空白以外の空白を無視するように指示するものです。これを使えば、正規表現を (少しは) 読みやすい単位に分割して使うことができるでしょう。あとで述べる、埋め込みコメントの機能とともに、Perl 5 を読みやすい言語にすることに貢献しています。See section 演算子と優先順位,にあげた C のコメントを削除する例を参照してください。
i 大文字小文字の区別をしないパターンマッチを行なう。
m 文字列を複数行として扱う。
s 文字列を単一行として扱う。
x 拡張正規表現を使用する。
があります。これらは通常、使用する区切り文字にスラッシュ以外のものを使うときでも、「/x 修飾子」のように書かれます。実際には、これらの修飾子は、 (?...) という新しい形式で正規表現の中に埋め込んでしまうこともできます。これについては、あとで述べます。
/x 修飾子について、もう少し説明しておきましょう。これは、正規表現のパーザに、バックスラッシュでエスケープされている空白、文字クラス内で使われている空白以外の空白を無視するように指示するものです。これを使えば、正規表現を (少しは) 読みやすい単位に分割して使うことができるでしょう。あとで述べる、埋め込みコメントの機能とともに、Perl 5 を読みやすい言語にすることに貢献しています。See section 演算子と優先順位,にあげた C のコメントを削除する例を参照してください。
1月16日水曜日: 整数演算
デフォルトでは、Perl は演算を浮動小数で行なわなければならないものとしていますが、
use integer;
と書けば、その場所から現在の BLOCK の終わりまでは、整数演算を行なってよいと、コンパイラに指示することができます。内部の BLOCK で、
no integer;
と書けば、その BLOCK の終わりまでは、指示を取り消すことになります。
use integer;
と書けば、その場所から現在の BLOCK の終わりまでは、整数演算を行なってよいと、コンパイラに指示することができます。内部の BLOCK で、
no integer;
と書けば、その BLOCK の終わりまでは、指示を取り消すことになります。
1月16日水曜日: 定数の畳み込み
C と同じように Perl でも、演算子に対するすべての引数がスタティックで、副作用がないと判断できれば、コンパイル時に式の評価を行なってしまいます。特に、変数置換の無いリテラルどうしの文字列連結はコンパイル時に行なわれます。バックスラッシュの解釈もコンパイル時に行なわれます。
'Now is the time for all' . "\n" .
'good men to come to.'
と書いても、内部的に 1 つの文字列になります。同様に
foreach $file (@filenames) {
if (-s $file > 5 + 100 * 2**16) { ... }
}
と書くとコンパイラは、式が表わす数値をあらかじめ計算しますので、インタプリタで計算する必要がなくなっています。
'Now is the time for all' . "\n" .
'good men to come to.'
と書いても、内部的に 1 つの文字列になります。同様に
foreach $file (@filenames) {
if (-s $file > 5 + 100 * 2**16) { ... }
}
と書くとコンパイラは、式が表わす数値をあらかじめ計算しますので、インタプリタで計算する必要がなくなっています。
1月11日金曜日: I/O 演算子
知っておいた方がよい I/O 演算子もいくつかあります。バッククォートで括られた文字列は、まず、ダブルクォート文字列のように、変数の展開が行なわれます。その後、シェルでの場合と同じように、コマンドとして解釈され、そのコマンドの出力がこの擬似リテラルの値となります。スカラコンテキストでは、出力すべてを含む一個の文字列が返されます。リストコンテキストでは、出力の 1 行 1 行が個々の要素となるリストが返されます。($/ を設定すれば、行の終わりを示す文字を変えることができます。)コマンドは、この擬似リテラルが評価されるごとに実行されます。コマンドのステータス値は $? に返されます ($? の解釈については、See section 定義済み変数,を参照してください)。csh での場合とは違って、結果のデータに対する変換は行なわれず、改行は改行のままです。どのシェルとも違って、シングルクォートがコマンド中の変数名を解釈させないようにすることはありません。シェルに$ を渡すには、バックスラッシュでエスケープしなければなりません。バッククォートの一般形は、qx// です。
山括弧の中のファイルハンドルを評価すると、そのファイルから、次の行を読み込むことになります (改行も含まれるので、未定義値が返される EOF に達するまでは、偽と評価される値が返ることはありません)。通常は、その値を変数に代入しなければなりませんが、自動的に代入される場合が 1 つだけあります。この入力シンボルが、while ループの条件式中に単独で現れた場合だけは、その値が自動的に変数 $_ に代入されます。(これは、奇妙に思えるかもしれませんが、ほとんどすべての Perl スクリプトでこれが必要になることでしょう。)いずれにせよ、以下のものは、お互いに同値なものです:
while ($_ = <STDIN>) { print; }
while (<STDIN>) { print; }
for (;<STDIN>;) { print; }
print while $_ = <STDIN>;
print while <STDIN>;
STDIN、STDOUT、STDERR というファイルハンドルは、あらかじめ定義されています。(stdin、stdout、stderr というファイルハンドルも、ローカルな名前でこれらのグローバルな名前が見えなくなっているパッケージを除けば、使用することができます。)その他のファイルハンドルは、open() 関数で作ることができます。
<FILEHANDLE> がリストを必要とするコンテキストで用いられると、1 要素に 1 行の入力行すべてからなるリストが返されます。これを使うと簡単に巨大なデータが作られてしまいますので、注意を要します。
ヌルファイルハンドル <> は特別で、sed や awk の動作をエミュレートするために使われます。<> からの入力は、標準入力からか、コマンドライン上に並べられた個々のファイルから行なわれます。動作の概要は、以下のようになります。最初に <> が評価されると、配列 @ARGV が調べられ、空であれば、$ARGV[0] に "-"を設定します。これは、open されるとき標準入力となります。その後、配列 @ARGV がファイル名のリストとして処理されます。
while (<>) {
... # 行ごとの処理
}
というループは、
unshift(@ARGV, '-') if $#ARGV < $[;
while ($ARGV = shift) {
open(ARGV, $ARGV);
while (<ARGV>) {
... # 行ごとの処理
}
}
のような Perl の擬似コードと等価です。わずらわしく書かなくても、動作します。実際に @ARGV を shift しますし、その時点のファイル名を変数 $ARGV に入れています。また、内部的にファイルハンドル ARGV を使っていて、<> は不思議な <ARGV> の同義語となっています。(上記の擬似コードは、<ARGV> を通常のものとして扱っているので、うまく動作しません。)
終的に、@ARGV に扱いたいと思っているファイル名が含まれるのであれば、最初に <> を評価する前に @ARGV を変更することも可能です。行番号 ($.) は、入力ファイルがあたかも 1 つの大きなファイルであるかのように、続けてカウントされます。(個々のファイルごとにリセットする方法は、perlfunc manpage の eof() の例を参照してください。)
最初から @ARGV に自分でファイルのリストを設定してもかまいません。スクリプトにスイッチを渡したいのであれば、Getopts モジュールを使うこともできますし、実際の処理の前に
while ($_ = $ARGV[0], /^-/) {
shift;
last if /^--$/;
if (/^-D(.*)/) { $debug = $1 }
if (/^-v/) { $verbose++ }
... # その他のスイッチ
}
while (<>) {
... # 個々のファイルに対するコード
}
のようなループを置くこともできます。
シンボル <> が「偽」を返すのは一度きりです。偽となったあとで、もう一度呼び出すと、新たに別の @ARGV を処理するものとみなされ、その時に @ARGV を設定しなおしていないと、STDIN から読み込むことになります。
山括弧の中の文字列が (<$foo> のような) スカラ変数の参照となっていれば、その変数が入力を行なうファイルハンドルの名前を示しているとみなされます。
山括弧の中の文字列がファイルハンドルでなければ、グロブを行なうファイル名のパターンと解釈され、コンテキストによって、ファイル名のリストか、そのリストの次のファイル名が返されます。まず、1 段階だけ $ の展開が行なわれますが、前の段落に書いた間接ファイルハンドルと同じになる、<$foo> のようには書けません。ファイル名グロブと解釈させるには <${foo}> のように中括弧を入れる必要があります。(別の方法として、glob($foo) と内部関数を呼ぶこともできます。おそらく、まず、こちらの方で試すのが正解でしょう。) 例:
while (<*.c>) {
chmod 0644, $_;
}
は、
open(FOO, "echo *.c | tr -s ' \t\r\f' '\\012\\012\\012\\012'|");
while (<FOO>) {
chop;
chmod 0644, $_;
}
と等価です。実際、現在はそのようにインプリメントされています。(つまり、マシン上に csh(1) がないと、スペースを含むファイル名は、うまく扱えないということです。)もちろん、もっと簡単に
chmod 0644, <*.c>;
と書けます。
グロブはシェルを呼び出しますから、自分で readdir() を呼んで、得られたファイル名に grep() した方が速い場合もあります。さらに、現在のインプリメントがシェルを使うために、(/bin/csh として tcsh(1L) をインストールしていない限り) glob() ルーティンで "Arg list too long" エラーが発生する場合があります。
山括弧の中のファイルハンドルを評価すると、そのファイルから、次の行を読み込むことになります (改行も含まれるので、未定義値が返される EOF に達するまでは、偽と評価される値が返ることはありません)。通常は、その値を変数に代入しなければなりませんが、自動的に代入される場合が 1 つだけあります。この入力シンボルが、while ループの条件式中に単独で現れた場合だけは、その値が自動的に変数 $_ に代入されます。(これは、奇妙に思えるかもしれませんが、ほとんどすべての Perl スクリプトでこれが必要になることでしょう。)いずれにせよ、以下のものは、お互いに同値なものです:
while ($_ = <STDIN>) { print; }
while (<STDIN>) { print; }
for (;<STDIN>;) { print; }
print while $_ = <STDIN>;
print while <STDIN>;
STDIN、STDOUT、STDERR というファイルハンドルは、あらかじめ定義されています。(stdin、stdout、stderr というファイルハンドルも、ローカルな名前でこれらのグローバルな名前が見えなくなっているパッケージを除けば、使用することができます。)その他のファイルハンドルは、open() 関数で作ることができます。
<FILEHANDLE> がリストを必要とするコンテキストで用いられると、1 要素に 1 行の入力行すべてからなるリストが返されます。これを使うと簡単に巨大なデータが作られてしまいますので、注意を要します。
ヌルファイルハンドル <> は特別で、sed や awk の動作をエミュレートするために使われます。<> からの入力は、標準入力からか、コマンドライン上に並べられた個々のファイルから行なわれます。動作の概要は、以下のようになります。最初に <> が評価されると、配列 @ARGV が調べられ、空であれば、$ARGV[0] に "-"を設定します。これは、open されるとき標準入力となります。その後、配列 @ARGV がファイル名のリストとして処理されます。
while (<>) {
... # 行ごとの処理
}
というループは、
unshift(@ARGV, '-') if $#ARGV < $[;
while ($ARGV = shift) {
open(ARGV, $ARGV);
while (<ARGV>) {
... # 行ごとの処理
}
}
のような Perl の擬似コードと等価です。わずらわしく書かなくても、動作します。実際に @ARGV を shift しますし、その時点のファイル名を変数 $ARGV に入れています。また、内部的にファイルハンドル ARGV を使っていて、<> は不思議な <ARGV> の同義語となっています。(上記の擬似コードは、<ARGV> を通常のものとして扱っているので、うまく動作しません。)
終的に、@ARGV に扱いたいと思っているファイル名が含まれるのであれば、最初に <> を評価する前に @ARGV を変更することも可能です。行番号 ($.) は、入力ファイルがあたかも 1 つの大きなファイルであるかのように、続けてカウントされます。(個々のファイルごとにリセットする方法は、perlfunc manpage の eof() の例を参照してください。)
最初から @ARGV に自分でファイルのリストを設定してもかまいません。スクリプトにスイッチを渡したいのであれば、Getopts モジュールを使うこともできますし、実際の処理の前に
while ($_ = $ARGV[0], /^-/) {
shift;
last if /^--$/;
if (/^-D(.*)/) { $debug = $1 }
if (/^-v/) { $verbose++ }
... # その他のスイッチ
}
while (<>) {
... # 個々のファイルに対するコード
}
のようなループを置くこともできます。
シンボル <> が「偽」を返すのは一度きりです。偽となったあとで、もう一度呼び出すと、新たに別の @ARGV を処理するものとみなされ、その時に @ARGV を設定しなおしていないと、STDIN から読み込むことになります。
山括弧の中の文字列が (<$foo> のような) スカラ変数の参照となっていれば、その変数が入力を行なうファイルハンドルの名前を示しているとみなされます。
山括弧の中の文字列がファイルハンドルでなければ、グロブを行なうファイル名のパターンと解釈され、コンテキストによって、ファイル名のリストか、そのリストの次のファイル名が返されます。まず、1 段階だけ $ の展開が行なわれますが、前の段落に書いた間接ファイルハンドルと同じになる、<$foo> のようには書けません。ファイル名グロブと解釈させるには <${foo}> のように中括弧を入れる必要があります。(別の方法として、glob($foo) と内部関数を呼ぶこともできます。おそらく、まず、こちらの方で試すのが正解でしょう。) 例:
while (<*.c>) {
chmod 0644, $_;
}
は、
open(FOO, "echo *.c | tr -s ' \t\r\f' '\\012\\012\\012\\012'|");
while (<FOO>) {
chop;
chmod 0644, $_;
}
と等価です。実際、現在はそのようにインプリメントされています。(つまり、マシン上に csh(1) がないと、スペースを含むファイル名は、うまく扱えないということです。)もちろん、もっと簡単に
chmod 0644, <*.c>;
と書けます。
グロブはシェルを呼び出しますから、自分で readdir() を呼んで、得られたファイル名に grep() した方が速い場合もあります。さらに、現在のインプリメントがシェルを使うために、(/bin/csh として tcsh(1L) をインストールしていない限り) glob() ルーティンで "Arg list too long" エラーが発生する場合があります。
1月10日木曜日: クォートとクォートのような演算子
クォートはリテラル値であると考えるのが普通ですが、Perl において、クォートは演算子として働き、さまざまな展開やパターンマッチの機能を持っています。そのような動作をさせるのに、Perl は慣習的にクォート文字を使っていますが、どの種類のクォートも、自分でクォート文字を選べるようになっています。以下の表では、{} がその選んだ区切文字のペアを示しています。選んだ区切文字が括弧の類でない場合には、前後の文字として同一のものを使いますが、4 つの括弧 ((), <>, [], {}) の場合にはネストできます。
通常記法 汎用記法 意味 展開
==========================================
'' q{} リテラル 不可
"" qq{} リテラル 可
`` qx{} コマンド 可
qw{} 単語リスト 不可
// m{} パターンマッチ 可
s{}{} 置換 可
tr{}{} 変換 不可
展開が行なわれる構文では、"$" や "@" で始まる変数が、以下のシーケンスと同時に展開されます:
\t タブ
\n 改行
\r 復帰
\f 改ページ
\v 垂直タブ (それが何であっても)
(訳注: これは使えないように見える)
\b バックスペース
\a アラーム (ベル)
\e エスケープ
\033 8 進数で表した文字
\x1b 16 進数で表した文字
\c[ コントロール文字
\l 次の文字を小文字にする
\u 次の文字を大文字にする
\L \E まで小文字にする
\U \E まで大文字にする
\E 変更の終わり
\Q \E まで正規表現のメタ文字をクォートする
パターンはさらに、正規表現として展開が行なわれます。これは、変数が展開された後の 2 回目のパスで行なわれるので、変数に正規表現を含めておき、パターンの中へ展開することができます。もし、そうしたくないのであれば、\Q を使うと変数の内容を文字どおりに展開することができます。
上記のものを除けば、複数の段階を踏んで展開が行なわれることはありません。特に、シェルのプログラマの期待とは裏腹に、バッククォートはダブルクォートの中では展開されませんし、シングルクォートがダブルクォートの中で使われても、変数の展開を妨げることはありません。
?PATTERN?
これは、reset() 演算子を呼び出すごとに 1 度だけしかマッチしないことを除いては /pattern/ による検索と全く同じです。たとえば、ファイルの集まりの中で個々のファイルについて、あるものを探すとき、最初の 1 つだけの存在がわかれば良いのであれば、この機能を使って最適化をはかることができます。現在のパッケージにローカルとなっている ?PATTERN? のパターンだけが reset されます。 この方法は、あまりお勧めしません。Perl の将来のバージョンでは削除されるかもしれません。
m/PATTERN/gimosx
/PATTERN/gimosx
パターンマッチで文字列検索を行ない、スカラコンテキストでは真 (1) または偽 (") を返す。=~ 演算子か !~ 演算子で検索対象の文字列を示さなかったときには、$_の文字列が検索対象となります。(=~ で指定される文字列は、左辺値である必要はありません。式を評価した結果でもかまいませんが、=~ の優先順位がいくぶん高いことに注意してください。)perlre manpage を参照してください。 オプションには、
g グローバルにマッチ、つまり、すべてを探し出す
i 大文字、小文字を区別しない
m 文字列を複数行として扱う
o パターンのコンパイルを 1 度だけにする
s 文字列を単一行として扱う
x 拡張正規表現を使用する
があります。 区切文字が "/" のときには、最初の m は付けても付けなくてもかまいません。 m を付けるときには、英数字でも空白でもない、任意の任意の文字のペアを、区切文字として使うことができます。これは "/" を含む UNIX のパス名にパターンパッチを行なうときに便利でしょう。\/ といった LTS (楊枝偏執症候群) を避けるためにも。 PATTERN には、変数が含まれていてもよく、パターンが評価されるごとに、変数は展開され (パターンが再コンパイルされ) ます。(2 つの変数 $) と $| は文字列の終わりを調べるパターンであると解釈されるので、展開されません。)パターンがコンパイルされるのを 1 度だけにしたい場合には、終わりの区切文字の後に /o 修飾子を付けます。これにより、実行時に再コンパイルが頻繁に起こることが避けられ、展開する値がスクリプトの実行中に変化しない場合に有効なものとなります。しかし、/o を付けることは、パターンの中の変数を変更しないことを約束するものです。変更したとしても、Perl がそれに気付くことはありません。 PATTERN を評価した結果が空文字列となった場合には、最後に実行され (コンパイルに成功し) た正規表現が、代わりに使われます。 パターンマッチが、リスト値が要求されるコンテキストで使われると、パターンの中の括弧で括られた部分列にマッチしたもので構成されるリストを返します。これは、($1, $2, $3, ...) ということです。(この場合、$1 なども設定されます。この点で Perl 4 の動作と違っています。)マッチが失敗した場合には、空配列が返されます。マッチが成功した場合で、括弧が無い場合には、リスト値 (1) が返されます。 例:
open(TTY, '/dev/tty');
<TTY> =~ /^y/i && foo(); # 要望により foo を実行
if (/Version: *([0-9.]*)/) { $version = $1; }
next if m#^/usr/spool/uucp#;
# 安上がりな grep
$arg = shift;
while (<>) {
print if /$arg/o; # 1 度だけコンパイル
}
if (($F1, $F2, $Etc) = ($foo =~ /^(\S+)\s+(\S+)\s*(.*)/))
最後の例は、$foo を最初の 2 つの単語と行の残りに分解し、$F1 と $F2 と $Etc に代入しています。変数に代入されれば、すなわちパターンがマッチすれば、if の条件が真となります。 /g 修飾子は、グローバルなパターンマッチを指定するもので、文字列の中で可能な限りたくさんマッチを行ないます。この動作は、コンテキストに依存します。リストコンテキストでは、正規表現内のすべての括弧付けされたものにマッチした部分文字列全部のリストが返されます。括弧がなければ、パターン全体を括弧で括っていたかのように、すべてのマッチした文字列のリストが返されます。 スカラコンテキストでは、m//g は文字列内で繰り返しを行ない、マッチするごとに「真」を返し、最終的にマッチしなくなったときに「偽」を返します。(言い換えると、前回止まった場所を覚えていて、その場所から検索を再開するということです。文字列の現在の検索位置は、関数 pos() を使って知ることができます。See section 組み込み関数,を参照してください。)いかなる方法でも、対象の文字列を変更すると、検索位置は先頭にリセットされます。 例:
# リストコンテキスト
($one,$five,$fifteen) = (`uptime` =~ /(\d+\.\d+)/g);
# スカラコンテキスト
$/ = ""; $* = 1; # Perl 5 では、$* は使わないほうがよい
while ($paragraph = <>) {
while ($paragraph =~ /[a-z]['")]*[.!?]+['")]*\s/g) {
$sentences++;
}
}
print "$sentences\n";
q/STRING/
'STRING'
シングルクォートされた、リテラル文字列です。バックスラッシュは、後ろに続くものが区切文字か、別のバックスラッシュである場合を除いて無視されます。区切文字やバックスラッシュが続く場合には、その区切文字自身もしくはバックスラッシュそのものが展開されます。
$foo = q!I said, "You said, 'She said it.'"!;
$bar = q('This is it.');
qq/STRING/
"STRING"
ダブルクォートされた、リテラル文字列です。
$_ .= qq
(*** The previous line contains the naughty word "$1".\n)
if /(tcl|rexx|python)/; # :-)
qx/STRING/
`STRING`
展開され、システムのコマンドとして実行される文字列です。そのコマンドの、標準出力を集めたものが返されます。スカラコンテキストでは、(複数行を含むかもしれない) 1 つの文字列が戻ってきます。リストコンテキストでは、($/ もしくは $INPUT_RECORD_SEPARATOR をどのように設定していても) 行のリストを返します。
$today = qx{ date };
詳しくは「See section I/O 演算子,」の節を参照してください。
qw/STRING/
埋め込まれた空白を区切文字として、STRING から抜き出した単語のリストを返します。これは、
split(' ', q/STRING/);
と完全に同じになります。 よく行なわれる例としては:
use POSIX qw( setlocale localeconv );
@EXPORT = qw( foo bar baz );
というものがあります。
s/PATTERN/REPLACEMENT/egimosx
文字列中でパターンを検索し、もし見つかれば、置換テキストで置き換え、置換した数を返します。見つからなければ、偽 (0) を返します。 =~ 演算子や !~ 演算子によって文字列が指定されていなければ、変数 $_ が検索され、修正されます。(=~ で指定される文字列は、スカラ変数、配列要素、ハッシュ要素、あるいは、これらへの代入式といった左辺値でなければなりません。) あとで述べますが、区切り文字はスラッシュとは限りません。シングルクォートを区切り文字として使った場合には、PATTERN にも REPLACEMENT にも変数の展開を行ないません。 それ以外の場合、文字列の最後を表わすものには見えない $ が PATTERN に含まれると、実行時に変数がパターン内に展開されます。最初に変数が展開されるときにだけパターンのコンパイルを行ないたいときには、/o オプションを使ってください。パターンの評価結果が空文字列になった場合には、最後に実行され (コンパイルに成功し) た正規表現が代わりに使われます。これについてさらに詳しくは、See section 正規表現,を参照してください。 オプションには、
e 式の右側の評価を行なう
g グローバルな置換、つまり見つかったものすべて
i 大文字、小文字を区別しないで検索
m 文字列を複数行として扱う
o パターンのコンパイルを 1 度だけにする
s 文字列を単一行として扱う
x 拡張正規表現を使用する
があります。 英数字、空白ではない任意の区切り文字で、スラッシュを置き換えることができます。先に述べたように、シングルクォートを使うと置換文字列での展開はされません (/e 修飾子を使えば可能です)。バッククォートを用いると、置換文字列をコマンドとして実行して、その出力が実際の置換文字列に使われます。 PATTERN を括弧類で括った場合には、REPLACEMENT 用にもう一組の区切り文字を用意します。これは、括弧類であっても、なくてもかまいません。例: s(foo)(bar) や s<foo>/bar/。/e は置換文字列を完全な Perl の式として解釈し、その場所で直ちにeval() します。しかし、これはコンパイル時に構文チェックされます。 例:
s/\bgreen\b/mauve/g; # wintergreen は変更しない
$path =~ s|/usr/bin|/usr/local/bin|;
s/Login: $foo/Login: $bar/; # 実行時パターン
($foo = $bar) =~ s/this/that/;
$count = ($paragraph =~ s/Mister\b/Mr./g);
$_ = 'abc123xyz';
s/\d+/$&*2/e; # 'abc246xyz' となる
s/\d+/sprintf("%5d",$&)/e; # 'abc 246xyz'
s/\w/$& x 2/eg; # 'aabbcc 224466xxyyzz'
s/%(.)/$percent{$1}/g; # パーセントエスケー
# プを変更; /e なし
s/%(.)/$percent{$1} || $&/ge; # 式となるので /e
s/^=(\w+)/&pod($1)/ge; # 関数呼び出しを使う
# /e はネスト可能;
# $_ に単純に埋め込まれた変数を展開する
s/(\$\w+)/$1/eeg;
# C コメントの削除
$program =~ s {
/\* (?# 開始区切り文字にマッチ)
.*? (?# 最短一致でマッチ)
\*/ (?# 終了区切り文字にマッチ)
} []gsx;
s/^\s*(.*?)\s*$/$1/; # 空白の切り詰め
s/([^ ]*) *([^ ]*)/$2 $1/; # 最初の 2 語の入れ替え
最後の例で \ の代わりに $ を使っているのに注意してください。sed と違って、 \<数字> の形式はパターンの方でのみ使用できます。その他の場所では、$<数字 > を使います。 ときには、/g を付けるだけでは、すべてを変更することができないことがあります。2 つ例を示します:
# 整数の適切な位置にコンマを入れる
1 while s/(.*\d)(\d\d\d)/$1,$2/g; # perl4
1 while s/(\d)(\d\d\d)(?!\d)/$1,$2/g; # perl5
# タブを 8 カラムのスペースに展開
1 while s/\t+/' ' x (length($&)*8 - length($`)%8)/e;
tr/SEARCHLIST/REPLACEMENTLIST/cds
y/SEARCHLIST/REPLACEMENTLIST/cds
検索リスト (SEARCHLIST) に含まれる文字を、対応する置換リスト (REPLACEMENTLIST) の文字に変換します。置換または削除が行なわれた、文字数を返します。=~ 演算子や =! 演算子で文字列が指定されていなければ、$_の文字列が変換されます。(=~ で指定される文字列は、スカラ変数、配列要素、ハッシュ要素、あるいは、これらへの代入式といった左辺値でなければなりません。) sed の信仰者のために y が tr の同義語として提供されています。SEARCHLIST を括弧類で括った場合には、REPLACEMENTLIST 用に、もう一組の区切り文字を用意します。これは、括弧類であっても、なくてもかまいません。
例: tr[A-Z][a-z] や tr(+-*/)/ABCD/。
オプションには、
c SEARCHLIST を補集合にする
d 見つかったが置換されなかった文字を削除する
s 置換された文字が重なったときに圧縮する
があります。 /c 修飾子が指定されると、SEARCHLIST には補集合が指定されたものと解釈されます。/d 修飾子が指定されると、SEARCHLIST に指定されて、REPLACEMENTLIST に対応するものがない文字が削除されます。(これは、SEARCHLIST で見つかったものを削除する、ただそれだけの、ある種の tr プログラムの動作よりと比べれば、いく分柔軟なものになっています。)/s 修飾子が指定されると、同じ文字に置き換えられた文字の並びを、その文字 1 文字だけに圧縮します。 /d 修飾子が使われると、REPLACEMENTLIST は、常に指定された通りに解釈されます。/d が指定されない場合で、REPLACEMENTLIST が SEARCHLIST よりも短いと、同じ長さになるまで、REPLACEMENTLIST の最後の文字が繰り返されているものとして扱われます。REPLACEMENTLIST が空文字列でのときには、SEARCHLIST と同じになります。後者は、ある文字クラスに含まれる文字数を数えるときや、ある文字クラスの文字の並びを圧縮するようなときに便利です。 例:
$ARGV[1] =~ tr/A-Z/a-z/; # 小文字に統一
$cnt = tr/*/*/; # $_ 内の * を数える
$cnt = $sky =~ tr/*/*/; # $sky 内の * を数える
$cnt = tr/0-9//; # $_ 内の数字を数える
tr/a-zA-Z//s; # bookkeeper -> bokeper
($HOST = $host) =~ tr/a-z/A-Z/;
tr/a-zA-Z/ /cs; # 英字以外を 1 つの
# スペースに変換する
tr [\200-\377]
[\000-\177]; # 8th bit 目を削除
変換テーブルはコンパイル時に作られるので、SEARCHLIST も REPLACEMENTLIST もダブルクォート展開の対象とはなりません。変数を使いたい場合には、eval() を使わなければならないということです:
eval "tr/$oldlist/$newlist/";
die $@ if $@;
eval "tr/$oldlist/$newlist/, 1" or die $@;
通常記法 汎用記法 意味 展開
==========================================
'' q{} リテラル 不可
"" qq{} リテラル 可
`` qx{} コマンド 可
qw{} 単語リスト 不可
// m{} パターンマッチ 可
s{}{} 置換 可
tr{}{} 変換 不可
展開が行なわれる構文では、"$" や "@" で始まる変数が、以下のシーケンスと同時に展開されます:
\t タブ
\n 改行
\r 復帰
\f 改ページ
\v 垂直タブ (それが何であっても)
(訳注: これは使えないように見える)
\b バックスペース
\a アラーム (ベル)
\e エスケープ
\033 8 進数で表した文字
\x1b 16 進数で表した文字
\c[ コントロール文字
\l 次の文字を小文字にする
\u 次の文字を大文字にする
\L \E まで小文字にする
\U \E まで大文字にする
\E 変更の終わり
\Q \E まで正規表現のメタ文字をクォートする
パターンはさらに、正規表現として展開が行なわれます。これは、変数が展開された後の 2 回目のパスで行なわれるので、変数に正規表現を含めておき、パターンの中へ展開することができます。もし、そうしたくないのであれば、\Q を使うと変数の内容を文字どおりに展開することができます。
上記のものを除けば、複数の段階を踏んで展開が行なわれることはありません。特に、シェルのプログラマの期待とは裏腹に、バッククォートはダブルクォートの中では展開されませんし、シングルクォートがダブルクォートの中で使われても、変数の展開を妨げることはありません。
?PATTERN?
これは、reset() 演算子を呼び出すごとに 1 度だけしかマッチしないことを除いては /pattern/ による検索と全く同じです。たとえば、ファイルの集まりの中で個々のファイルについて、あるものを探すとき、最初の 1 つだけの存在がわかれば良いのであれば、この機能を使って最適化をはかることができます。現在のパッケージにローカルとなっている ?PATTERN? のパターンだけが reset されます。 この方法は、あまりお勧めしません。Perl の将来のバージョンでは削除されるかもしれません。
m/PATTERN/gimosx
/PATTERN/gimosx
パターンマッチで文字列検索を行ない、スカラコンテキストでは真 (1) または偽 (") を返す。=~ 演算子か !~ 演算子で検索対象の文字列を示さなかったときには、$_の文字列が検索対象となります。(=~ で指定される文字列は、左辺値である必要はありません。式を評価した結果でもかまいませんが、=~ の優先順位がいくぶん高いことに注意してください。)perlre manpage を参照してください。 オプションには、
g グローバルにマッチ、つまり、すべてを探し出す
i 大文字、小文字を区別しない
m 文字列を複数行として扱う
o パターンのコンパイルを 1 度だけにする
s 文字列を単一行として扱う
x 拡張正規表現を使用する
があります。 区切文字が "/" のときには、最初の m は付けても付けなくてもかまいません。 m を付けるときには、英数字でも空白でもない、任意の任意の文字のペアを、区切文字として使うことができます。これは "/" を含む UNIX のパス名にパターンパッチを行なうときに便利でしょう。\/ といった LTS (楊枝偏執症候群) を避けるためにも。 PATTERN には、変数が含まれていてもよく、パターンが評価されるごとに、変数は展開され (パターンが再コンパイルされ) ます。(2 つの変数 $) と $| は文字列の終わりを調べるパターンであると解釈されるので、展開されません。)パターンがコンパイルされるのを 1 度だけにしたい場合には、終わりの区切文字の後に /o 修飾子を付けます。これにより、実行時に再コンパイルが頻繁に起こることが避けられ、展開する値がスクリプトの実行中に変化しない場合に有効なものとなります。しかし、/o を付けることは、パターンの中の変数を変更しないことを約束するものです。変更したとしても、Perl がそれに気付くことはありません。 PATTERN を評価した結果が空文字列となった場合には、最後に実行され (コンパイルに成功し) た正規表現が、代わりに使われます。 パターンマッチが、リスト値が要求されるコンテキストで使われると、パターンの中の括弧で括られた部分列にマッチしたもので構成されるリストを返します。これは、($1, $2, $3, ...) ということです。(この場合、$1 なども設定されます。この点で Perl 4 の動作と違っています。)マッチが失敗した場合には、空配列が返されます。マッチが成功した場合で、括弧が無い場合には、リスト値 (1) が返されます。 例:
open(TTY, '/dev/tty');
<TTY> =~ /^y/i && foo(); # 要望により foo を実行
if (/Version: *([0-9.]*)/) { $version = $1; }
next if m#^/usr/spool/uucp#;
# 安上がりな grep
$arg = shift;
while (<>) {
print if /$arg/o; # 1 度だけコンパイル
}
if (($F1, $F2, $Etc) = ($foo =~ /^(\S+)\s+(\S+)\s*(.*)/))
最後の例は、$foo を最初の 2 つの単語と行の残りに分解し、$F1 と $F2 と $Etc に代入しています。変数に代入されれば、すなわちパターンがマッチすれば、if の条件が真となります。 /g 修飾子は、グローバルなパターンマッチを指定するもので、文字列の中で可能な限りたくさんマッチを行ないます。この動作は、コンテキストに依存します。リストコンテキストでは、正規表現内のすべての括弧付けされたものにマッチした部分文字列全部のリストが返されます。括弧がなければ、パターン全体を括弧で括っていたかのように、すべてのマッチした文字列のリストが返されます。 スカラコンテキストでは、m//g は文字列内で繰り返しを行ない、マッチするごとに「真」を返し、最終的にマッチしなくなったときに「偽」を返します。(言い換えると、前回止まった場所を覚えていて、その場所から検索を再開するということです。文字列の現在の検索位置は、関数 pos() を使って知ることができます。See section 組み込み関数,を参照してください。)いかなる方法でも、対象の文字列を変更すると、検索位置は先頭にリセットされます。 例:
# リストコンテキスト
($one,$five,$fifteen) = (`uptime` =~ /(\d+\.\d+)/g);
# スカラコンテキスト
$/ = ""; $* = 1; # Perl 5 では、$* は使わないほうがよい
while ($paragraph = <>) {
while ($paragraph =~ /[a-z]['")]*[.!?]+['")]*\s/g) {
$sentences++;
}
}
print "$sentences\n";
q/STRING/
'STRING'
シングルクォートされた、リテラル文字列です。バックスラッシュは、後ろに続くものが区切文字か、別のバックスラッシュである場合を除いて無視されます。区切文字やバックスラッシュが続く場合には、その区切文字自身もしくはバックスラッシュそのものが展開されます。
$foo = q!I said, "You said, 'She said it.'"!;
$bar = q('This is it.');
qq/STRING/
"STRING"
ダブルクォートされた、リテラル文字列です。
$_ .= qq
(*** The previous line contains the naughty word "$1".\n)
if /(tcl|rexx|python)/; # :-)
qx/STRING/
`STRING`
展開され、システムのコマンドとして実行される文字列です。そのコマンドの、標準出力を集めたものが返されます。スカラコンテキストでは、(複数行を含むかもしれない) 1 つの文字列が戻ってきます。リストコンテキストでは、($/ もしくは $INPUT_RECORD_SEPARATOR をどのように設定していても) 行のリストを返します。
$today = qx{ date };
詳しくは「See section I/O 演算子,」の節を参照してください。
qw/STRING/
埋め込まれた空白を区切文字として、STRING から抜き出した単語のリストを返します。これは、
split(' ', q/STRING/);
と完全に同じになります。 よく行なわれる例としては:
use POSIX qw( setlocale localeconv );
@EXPORT = qw( foo bar baz );
というものがあります。
s/PATTERN/REPLACEMENT/egimosx
文字列中でパターンを検索し、もし見つかれば、置換テキストで置き換え、置換した数を返します。見つからなければ、偽 (0) を返します。 =~ 演算子や !~ 演算子によって文字列が指定されていなければ、変数 $_ が検索され、修正されます。(=~ で指定される文字列は、スカラ変数、配列要素、ハッシュ要素、あるいは、これらへの代入式といった左辺値でなければなりません。) あとで述べますが、区切り文字はスラッシュとは限りません。シングルクォートを区切り文字として使った場合には、PATTERN にも REPLACEMENT にも変数の展開を行ないません。 それ以外の場合、文字列の最後を表わすものには見えない $ が PATTERN に含まれると、実行時に変数がパターン内に展開されます。最初に変数が展開されるときにだけパターンのコンパイルを行ないたいときには、/o オプションを使ってください。パターンの評価結果が空文字列になった場合には、最後に実行され (コンパイルに成功し) た正規表現が代わりに使われます。これについてさらに詳しくは、See section 正規表現,を参照してください。 オプションには、
e 式の右側の評価を行なう
g グローバルな置換、つまり見つかったものすべて
i 大文字、小文字を区別しないで検索
m 文字列を複数行として扱う
o パターンのコンパイルを 1 度だけにする
s 文字列を単一行として扱う
x 拡張正規表現を使用する
があります。 英数字、空白ではない任意の区切り文字で、スラッシュを置き換えることができます。先に述べたように、シングルクォートを使うと置換文字列での展開はされません (/e 修飾子を使えば可能です)。バッククォートを用いると、置換文字列をコマンドとして実行して、その出力が実際の置換文字列に使われます。 PATTERN を括弧類で括った場合には、REPLACEMENT 用にもう一組の区切り文字を用意します。これは、括弧類であっても、なくてもかまいません。例: s(foo)(bar) や s<foo>/bar/。/e は置換文字列を完全な Perl の式として解釈し、その場所で直ちにeval() します。しかし、これはコンパイル時に構文チェックされます。 例:
s/\bgreen\b/mauve/g; # wintergreen は変更しない
$path =~ s|/usr/bin|/usr/local/bin|;
s/Login: $foo/Login: $bar/; # 実行時パターン
($foo = $bar) =~ s/this/that/;
$count = ($paragraph =~ s/Mister\b/Mr./g);
$_ = 'abc123xyz';
s/\d+/$&*2/e; # 'abc246xyz' となる
s/\d+/sprintf("%5d",$&)/e; # 'abc 246xyz'
s/\w/$& x 2/eg; # 'aabbcc 224466xxyyzz'
s/%(.)/$percent{$1}/g; # パーセントエスケー
# プを変更; /e なし
s/%(.)/$percent{$1} || $&/ge; # 式となるので /e
s/^=(\w+)/&pod($1)/ge; # 関数呼び出しを使う
# /e はネスト可能;
# $_ に単純に埋め込まれた変数を展開する
s/(\$\w+)/$1/eeg;
# C コメントの削除
$program =~ s {
/\* (?# 開始区切り文字にマッチ)
.*? (?# 最短一致でマッチ)
\*/ (?# 終了区切り文字にマッチ)
} []gsx;
s/^\s*(.*?)\s*$/$1/; # 空白の切り詰め
s/([^ ]*) *([^ ]*)/$2 $1/; # 最初の 2 語の入れ替え
最後の例で \ の代わりに $ を使っているのに注意してください。sed と違って、 \<数字> の形式はパターンの方でのみ使用できます。その他の場所では、$<数字 > を使います。 ときには、/g を付けるだけでは、すべてを変更することができないことがあります。2 つ例を示します:
# 整数の適切な位置にコンマを入れる
1 while s/(.*\d)(\d\d\d)/$1,$2/g; # perl4
1 while s/(\d)(\d\d\d)(?!\d)/$1,$2/g; # perl5
# タブを 8 カラムのスペースに展開
1 while s/\t+/' ' x (length($&)*8 - length($`)%8)/e;
tr/SEARCHLIST/REPLACEMENTLIST/cds
y/SEARCHLIST/REPLACEMENTLIST/cds
検索リスト (SEARCHLIST) に含まれる文字を、対応する置換リスト (REPLACEMENTLIST) の文字に変換します。置換または削除が行なわれた、文字数を返します。=~ 演算子や =! 演算子で文字列が指定されていなければ、$_の文字列が変換されます。(=~ で指定される文字列は、スカラ変数、配列要素、ハッシュ要素、あるいは、これらへの代入式といった左辺値でなければなりません。) sed の信仰者のために y が tr の同義語として提供されています。SEARCHLIST を括弧類で括った場合には、REPLACEMENTLIST 用に、もう一組の区切り文字を用意します。これは、括弧類であっても、なくてもかまいません。
例: tr[A-Z][a-z] や tr(+-*/)/ABCD/。
オプションには、
c SEARCHLIST を補集合にする
d 見つかったが置換されなかった文字を削除する
s 置換された文字が重なったときに圧縮する
があります。 /c 修飾子が指定されると、SEARCHLIST には補集合が指定されたものと解釈されます。/d 修飾子が指定されると、SEARCHLIST に指定されて、REPLACEMENTLIST に対応するものがない文字が削除されます。(これは、SEARCHLIST で見つかったものを削除する、ただそれだけの、ある種の tr プログラムの動作よりと比べれば、いく分柔軟なものになっています。)/s 修飾子が指定されると、同じ文字に置き換えられた文字の並びを、その文字 1 文字だけに圧縮します。 /d 修飾子が使われると、REPLACEMENTLIST は、常に指定された通りに解釈されます。/d が指定されない場合で、REPLACEMENTLIST が SEARCHLIST よりも短いと、同じ長さになるまで、REPLACEMENTLIST の最後の文字が繰り返されているものとして扱われます。REPLACEMENTLIST が空文字列でのときには、SEARCHLIST と同じになります。後者は、ある文字クラスに含まれる文字数を数えるときや、ある文字クラスの文字の並びを圧縮するようなときに便利です。 例:
$ARGV[1] =~ tr/A-Z/a-z/; # 小文字に統一
$cnt = tr/*/*/; # $_ 内の * を数える
$cnt = $sky =~ tr/*/*/; # $sky 内の * を数える
$cnt = tr/0-9//; # $_ 内の数字を数える
tr/a-zA-Z//s; # bookkeeper -> bokeper
($HOST = $host) =~ tr/a-z/A-Z/;
tr/a-zA-Z/ /cs; # 英字以外を 1 つの
# スペースに変換する
tr [\200-\377]
[\000-\177]; # 8th bit 目を削除
変換テーブルはコンパイル時に作られるので、SEARCHLIST も REPLACEMENTLIST もダブルクォート展開の対象とはなりません。変数を使いたい場合には、eval() を使わなければならないということです:
eval "tr/$oldlist/$newlist/";
die $@ if $@;
eval "tr/$oldlist/$newlist/, 1" or die $@;
1月10日木曜日: Perl にない C の演算子
C にあって Perl に無いものは以下の通りです:
単項 &
アドレス演算子。("\" 演算子がリファレンスのために用いられます。)
単項 *
被アドレス参照演算子。 (Perl の被参照プリフィクス演算子が型づけを行なう: $, @, %, &。)
(型)
型のキャスト演算子。
単項 &
アドレス演算子。("\" 演算子がリファレンスのために用いられます。)
単項 *
被アドレス参照演算子。 (Perl の被参照プリフィクス演算子が型づけを行なう: $, @, %, &。)
(型)
型のキャスト演算子。
1月10日木曜日: 論理和と排他論理和
二項演算子の "or" は両側の式の論理和を返します。これは、優先順位がずっと低いことを除いて || と等価です。つまり、これも短絡演算を行ない、右側の式は左側の式が「偽」であった場合にのみ評価されます。
二項演算子の "xor" は両側の式の排他論理和を返します。これはもちろん、短絡ではありません。
二項演算子の "xor" は両側の式の排他論理和を返します。これはもちろん、短絡ではありません。