1. ホーム
  2. スクリプト・コラム
  3. パール

Perlの正規表現入門

2022-01-29 21:22:17

AKAと著者に感謝します。

Perlの正規表現
正規表現の3つの形式

正規表現でよくあるパターン

正規表現の8原則  

      正規表現はPerl言語の特徴であり、Perlのプログラムでは少々難しいものですが、しっかりと理解すれば、文字列処理作業はもちろんのこと、CGIプログラミングにも簡単に利用することができます。以下に、正規表現を書くための基本的な構文規則を列挙します。

9.1 正規表現の3つの形式
まず最初に、Perlのプログラムに存在する正規表現には3つの形式があることを知っておく必要があります。

マッチ: m/<regexp>;/ (m を省略して /<regexp>;/ とすることも可能です)

置換: s/<pattern>;/<replacement>;/

変換: tr/<pattern>;/<replacemnt>;/.

これらの3つの形式はすべて、一般に =~ または ! ~ (ここで "=~" は一致を意味し、ステートメント全体を通して同じように読みます、"! ~は不一致を意味し、文中ではdoesn'tと読みます)、左辺にスカラー変数が保留されています。もしそのような変数がなく、=~ ! ~ 演算子を使用した場合、デフォルトでは $_ 変数の内容を処理します。例を挙げると、次のようになる。

$str = "私はPerlが大好きです"。
$str =~ m/Perl/; # は、$str に "Perl" という文字列があれば "1" を返し、なければ "0" を返すという意味です。
$str =~ s/Perl/BASH/; # 変数 $str の中の "Perl" という文字列を "BASH" に置き換え、置き換えられた場合は "1" 、それ以外は "0" を返すことを意味します。
$str ! ~ tr/A-Z/a-z/; # 変数 $str の大文字をすべて小文字に変換し、変換できた場合は "0" 、できなかった場合は "1" を返すことを意味します。

また、利用可能です。

foreach (@array) { s/a/b/; }. # ここでの各ループは、@arrayの配列から1つの要素を取り出し、$_変数に格納し、$_に置換処理を行います。
while (<FILE>) { print if (m/error/); }. # これは少し複雑で、彼はFILEファイル内のエラー文字列を含むすべての行を表示することになります。

Perlの()付き正規表現は、マッチングや置換が発生した後、()内のパターンの順にPerlインタプリタが自動的にシステムに代入する $1, $2 ......................という仕組みになっています。次の例で考えてみましょう。

$string = "私はperlが大好きです"。
$string =~ s/(love)/<$1>;/; # この時点で $1 = "love" と置換した結果、$string は "I <love>; perl" に変化しているのです。
$string = "i love perl"。
$string =~ s/(i)(. *)(perl)/<$3>;$2<$1>;/; # ここで $1 = "i", $2 = "love ", $3 = "perl" で、置換後の $string は "<perl>; love <i>; " になっています。

置換操作 s/<pattern>;/<replacement>;/ は、最後に e または g 引数を付けて追加することもでき、これらはそれぞれ次のような意味をもちます。

s/<pattern>;/<replacement>;/g は、処理対象の文字列中の <pattern> にマッチするすべてのパターンを、最初に出現したパターンだけでなく、 <replacement> の文字列で置き換えることを意味します。
s/<pattern>;/<replacement>;/e は <replacementmnet> の部分が演算子として扱われることを意味し、この引数はあまり使用されないようです。

例えば、次のような例です。

$string = "i:love:perl";
$string =~ s/:/*/; #この時点で $string = "i*love:perl" となります。
$string = "i:love:perl";
$string =~ s/:/*/g; #この時点で $string = "i*love*perl" となります。
$string =~ tr/*/ /; #この時点で $string="i love perl";
$string = "www22cgi44";
$string =~ s/(\d+)/$1*2/e; # (/d+) は$stringの1つ以上の数字を表し、その数字に対して*2演算を行うので、最後の$stringは "www44cgi88" となります。

以下に完全な例を示す。

#! /usr/bin/perl

print"文字列を入力してください! \ЪЪЪ
$string = <STDIN>; # <STIDN>; は標準入力を意味し、ユーザーが文字列を入力することができます。
chop($string); # $stringから最後の改行文字を削除します。
if($string =~ /perl/){
  print("The string perl is in the input string! \ʕ-̫͡-ʔ
}

入力文字列にperlという文字列が含まれている場合、以下のようなメッセージが表示されます。

9.2 正規表現でよくあるパターン
正規表現でよくあるパターンを紹介します。

/pattern/ 結果 
. 改行文字を除くすべての文字にマッチします
x?は0個または1個のx文字列にマッチします。
x* は x 文字列に 0 回以上マッチしますが、可能な限り最小の回数にマッチします。
x+ は、1つ以上の x 文字列にマッチしますが、可能な限り最小限の回数にマッチします。
. * 任意の文字に0回または1回マッチする
. + 1回以上マッチする任意の文字
{m} は指定された文字列のうちちょうど m 個にマッチします。
{m,n} m以上n以下の指定された文字列にマッチします。
{m,} 指定された文字列のうち、m個以上にマッチします。
[] は [] 内の文字にマッチします
[^] は [] にマッチしない文字にマッチします。
[0-9] すべての数値文字にマッチします
[a-z] すべての小文字アルファベットにマッチします。
[^0-9] 数字以外のすべての文字にマッチします。
[^a-z] 小文字でないすべてのアルファベットにマッチします。
^ 文字で始まる文字にマッチします。
$ 文字で終わる文字にマッチします。
\ㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤの文字数にマッチします。
\d+ は、複数の数字文字列にマッチします([0-9]+ と同じ構文)。
\を使用する。
\⑭非数値、その他は⑭と同じ。
\a-zA-Z0-9 と同じ構文で、英数字の文字列。
\w+ と [a-zA-Z0-9]+ は同じ構文です。
\英数字以外の文字列で、[^a-zA-Z0-9]と同じ構文です。
\W+ と [^a-zA-Z0-9]+ は同じ構文です。
\s space, same syntax as [\n/Thanks].
\s+ Same as [\ntētérêtéf]+.
\S non-space, same syntax as [^n⊖Threef
\S+ と[^nttârâf]+ は同じ構文です。
\b は、文字と数字で区切られた文字列にマッチします。
\英字と数字で区切られていない文字列にマッチします。
a|b|c a文字またはb文字またはc文字にマッチする文字列をマッチさせます。
abc abcを含む文字列にマッチします
パターン)()記号は、見つかった文字列を記憶するもので、非常に便利な構文である。1つ目の()で見つかった文字列は$1変数、または \1変数になり、2つ目の()で見つかった文字列は$2変数、または \2変数になり、といった具合になります。 
引数 /pattern/i i は、英語の大文字小文字を無視して文字列をマッチさせることを意味します。
\ ■■■■■■■■■■不確定な文字がある場合、その文字を無効化させるために、その前に記号を付けなければならな いのです。

以下にいくつかの例を示します。   

説明の例
/perl/ perlを含む文字列を検索します。
/^perl/はperlで始まる文字列を検索します。
/perl$/ は、perl で終わる文字列を検索します。
/c|g|i/は、cまたはgまたはiを含む文字列を検索します。
/cg{2,4}i/は、cの後にgが2〜4個、そしてiが続く文字列を検索します。
/cg{2,}i/ cの後に2つ以上のgが続き、その後にiが続くものを探します。
/cg{2}i/ cの後に2つのgとiが続くものを探す
/cg*i/ は、/cg{0,1}i/ のように、c の後に 0 以上の g が続き、その後に i という文字列が続くものを探します。
/cg+i/ は、/cg{1,}i/ のように、c の後に複数の g が続き、その後に i という文字列が続くものを探します。
/cg?i/ は、/cg{0,1}i/ のように、c の後に 0 または 1 の g が続き、その後に文字列 i が続くものを見つけます。
/c.i/ は、c の後に任意の文字が続き、その後に文字列 i が続くことを検出します。
/c..i/ は、c の後に任意の2文字が続き、その後に文字列 i が続くことを検出します。
/[cgi]/ この3文字のいずれかにマッチする文字列を検索します。
/[^cgi]/ この3つの文字のどれにも該当しない文字列を検索します。
/d/ は数字にマッチする文字が見つかります。
/D/ finds characters that are not numbers, you can use /D+/ to represent one or more non-numeric string
/*/ *にマッチする文字を探します。*は正規表現で特別な意味を持つので、特殊記号の前に "second "を付けて特殊文字を無効とします。
/abc/i は abc にマッチする文字列を探し、その文字列の大文字と小文字は考慮されません

9.3 正規表現の8つの原則
  Unixでsed、awk、grepコマンドを使ったことがある人なら、Perlの正規表現には馴染みがないと思いますが、この機能により文字列に対して非常に強力な効果を発揮します。正規表現の使用はPerlのプログラムでしばしば見られ、CGIプログラミングでも例外ではありません。

  正規表現は、Perlを初めて学習する際には難しい部分ですが、その構文をマスターすれば、ほぼ無限のパターンマッチ機能を持つことができ、Perlプログラミングの作業のほとんどは、正規表現をマスターすることです。ここでは、正規表現を使うための8つの原則のうち、いくつかを紹介します。

  正規表現は、データとの戦いにおいて大連合を形成することができる--それはしばしば戦争となる。ここでは、覚えておくべき8つの原則を紹介します。

- 原則1.正規表現には3つの形式がある(一致(m/ /)、置換(s/ /eg)、変換(tr/ / /))。

- 原則2.正規表現はスカラーにのみマッチします( $scalar =~ m/a/; は動作します。 @array =~ m/a/ は @array をスカラーとして扱うため、動作しない場合があります)。

- 原則3.正規表現は、与えられたパターンに対して可能な限り早い段階でマッチします。デフォルトでは、正規表現は一度だけマッチまたは置換されます ( $a = '文字列 string2'; $a =~ s/string/ /; 結果、$a = '文字列 2' となります)。

- 原則4:正規表現は二重引用符が扱えるあらゆる文字を扱うことができる ( $a =~ m/$varb/ はマッチングの前に varb を変数に拡張します。$varb = 'a' $a = 'as' なら $a =~ s/$varb/ /; は $a =~ s/a/ /; と同等で、実行結果は $a = " s" となります)。

- 原則5:正規表現は評価過程で、結果状態と後方参照の2つのケースを生成する。a =~ m/pattern/は$aに部分文字列パターンがあるかどうかを示し、$a =~ s/(word1)(word2)/$2$1/ "二つの単語を入れ替える" を示しています。

- 原則6:正規表現の核となる力は、ワイルドカードと多重マッチ演算子、およびそれらの操作方法にある。a =~ m/w+/は1つ以上の単語文字にマッチし、$a =~ m/d/"は0つ以上の数字にマッチします。

- 原則7:複数の文字にマッチさせたい場合、Perlでは"|"を使って柔軟性を持たせています。m/(cat|dog)/と入力すると、"文字列のcatまたはdogにマッチするのと同じです。

- 原則8:Perlは(?...)構文を使って正規表現の拡張を提供します。(これについては、授業後に参照してください)。

これらの原則をすべて学びたいですか?簡単なものから始めて、試行錯誤を続けることをお勧めします。実際、$a =~ m/ERROR/と学ぶことが$aの部分文字列ERRORを探すことだとしたら、あなたはC言語のような低レベル言語よりも処理能力が高いということになります。

追加する。

良い
シンプルでわかりやすい
しかし、原文では
\a-zA-Z0-9 と同じ構文の英数字の文字列。 
これって間違っているような気がするのですが?
アンダースコアも含めて、つまり[a-zA-Z_0-9]とする必要があると記憶しています。

/cg*i/ は、/cg{0,1}i/ のように、c の後に 0 以上の g が続き、さらに i が続くものを見つけます。 
この文章も誤字です
次のようになります。
/cg*i/ は、/cg{0,}i/ のように、c の後に 0 以上の g が続き、その後に i が続くことを意味します。