正規表現で文字列のパターンマッチングするには (match / preg_match / search / =~)

各プログラミング言語での、正規表現で文字列のパターンマッチングをする方法。文字列全体ではなく部分マッチング。

Java

if ("Hello, world!".matches(".*wor.*")) {
    System.out.println("Match!");
}

Scala

if ("Hello, world!".matches(".*wor.*")) {
  println("Match!");
}

PHP

if (preg_match("/wor/", "Hello, world!")) {
    echo "Match!\n";
}

Python

import re
if re.compile("wor").search("Hello, world!"):
    print("Match!")

Ruby

if "Hello, world!" =~ /wor/
  puts("Match!")
end

Perl

if ("Hello, world!" =~ /wor/) {
    print("Match!\n");
}

bash

if [[ "Hello, world!" =~ "wor" ]]; then
    echo OK
fi

JavaScript

if ("Hello, world!".match(/wor/)) {
  console.log("Match!");
}

関連

PHP

preg_match という関数は、正規表現にマッチしたら 1, マッチしなかったら 0 が返される。正規表現が間違っているなどのエラーの際は false が返される。

preg_match("/a./", "abc\nabc"); // => 1
preg_match("/x./", "abc\nabc"); // => 0
preg_match("/a", "abc\nabc");   // => false

PHPでは 0if の条件の中に入れたら false とみなされるので、ifの条件式の中に素直に書ける。 (-> 論理値への変換)

if (preg_match("/x./", "abc\nabc")) { // NG
    ...;
}

preg_match は文字列全体のマッチングではなく、部分マッチングであるので、全体のマッチングをしたいのであれば、正規表現の '\A', '\z' を使うとよい。

正規表現はバックスラッシュを多用するので、"" ではなく '' で囲んだほうが便利。 "" で囲む場合は、"\\A", "\\z" などとバックスラッシュをたくさん書く必要がある。

preg_match('/bc/', "abc\nabc"); // => 1
preg_match('/\Abc\z/', "abc\nabc"); // => 0

パターン自体に / を使いたい場合、 \/ というふうにエスケープを使う必要がある。ファイルパスのパターンマッチングなどで、パターン自体に / をたくさん書く場合、全部エスケープするのは面倒なので、その場合はパターンの先頭と最後を / 以外の、例えば ! とかにするとよい。 "!\A/var/log/httpd/.+_log\z!" みたいに。先頭と最後を / にすると、 "/\A\/var\/log\/httpd\/.+_log\z/" と書かないといけない。その代わり、先頭と最後を ! にした場合は、パターン自体に含まれる !\! と書かないといけない。

3つ目の引数を渡すと、マッチした部分文字列を取得することができる。 -> 正規表現で文字列をキャプチャするには

preg_match 関数 | PHP Manual
http://www.php.net/manual/ja/function.preg-match.php

PCRE(Perlと互換性の高い正規表現)のパターン | PHP Manual
http://www.php.net/manual/ja/pcre.pattern.php

Python

コンパイルした正規表現をオブジェクトとして保持して、そのオブジェクトの matchメソッドなどを呼び出す。

import re

r = re.compile("bc")
print("match" if r.match("abc") else "unmatch") # => unmatch
r = re.compile("ab")
print("match" if r.match("abc") else "unmatch") # => match

matchメソッドは、文字列の先頭がマッチするかどうかであり、文字列全体のマッチングではなく、部分マッチングというわけでもない。

searchメソッドであれば、他の言語と同様に部分マッチングする。

match(str)
文字列の先頭がマッチするかどうかを判定し、マッチしたら MatchObject インスタンスを返し、マッチしなかったら None を返す
search(str)
文字列の先頭に限らずマッチするかどうかを判定し、マッチしたら MatchObject インスタンスを返し、マッチしなかったら None を返す
findall(str)
マッチする部分のすべてを MatchObject インスタンスのリストで返す。マッチしなければ空のリストを返す
finditer(str)
マッチする部分すべてを MatchObject インスタンスのイテレータで返す。マッチしなければ空のイテレータを返す

正規表現 HOWTO | Python 2.7 documentation
http://docs.python.jp/2/howto/regex.html

正規表現 HOWTO | Python 3 documentation
http://docs.python.jp/3/howto/regex.html

Ruby / JRuby

=~ という演算子は、正規表現にマッチしていたら、そのマッチした部分の先頭の文字のインデックスを返し、マッチしなければ nil を返す。

"abc\nabc\n" =~ /a./ # => 0
"abc\nabc\n" =~ /x./ # => nil

Rubyでは 0if の条件の中に入れたら true とみなされるので、ifの条件式として素直に使える。 (-> 論理値への変換)

if "abc\nabc\n" =~ /a./  # OK
  ...
end

文字列全体のマッチングではなく、部分マッチングであるので、全体のマッチングをしたいのであれば、正規表現の '\A', '\z' を使うとよい。

マッチングの後 $~$1, $2, $3 でマッチした部分文字列を取得することができる。 -> 正規表現で文字列をキャプチャするには

!~ という演算子は =~ の反対で、正規表現にマッチしていたら false を返し、マッチしなければ true を返す。インデックスは返さない。

/a./ !~ "abc\nabc\n" # => false
/x./ !~ "abc\nabc\n" # => true

Perl

=~ という演算子で、正規表現にマッチしていれば '1' を返し、マッチしていなければ '' を返す。

print "abc\nabc\n" =~ /a./;
# => 1
print "abc\nabc\n" =~ /a$/;
# => なにも出力しない

!~ という演算子は =~ の反対で、マッチしていれば '' を返し、マッチしていなければ 1 を返す。

正規表現の中にカッコで囲んだグループがあれば、マッチした場合、 $1, $2, $3, … にマッチした文字列が入る。
-> 正規表現のグルーピングにマッチした文字列

if文の条件式の中に正規表現だけを書いた場合は、その前に $_ =~ を付けたのと同じになる。

正規表現は普通は / で囲むが、文字列として書くこともできる。

print "abc\nabc\n" =~ ('a' . '.');
# => 1

sh (シェルスクリプト)

bashだと [[ というコマンドで =~ という演算子が使えて、正規表現でマッチングできる。

[[ "Hello, world!" =~ "wor" ]]
echo $?
# => 0

[[ "Hello, world!" =~ "unmatch" ]]
echo $?
# => 1

if文で使う例。

if [[ "Hello, world!" =~ "wor" ]]; then
    echo OK
fi

zshでもできるみたい。Ubuntuにあるdashではできなかった。

次はシェルの機能を使わずに grep でする方法。

echo "Hello, world!" | grep "wor" >/dev/null
echo $?
# => 0

echo "Hello, world!" | grep "unmatch" >/dev/null
echo $?
# => 1

これをif文で使う例。

if echo "Hello, world!" | grep "wor" >/dev/null; then
    echo OK
fi

JavaScript

"abc\nabc\n".match(/a./); // => ["ab"]
"abc\nabc\n".match(/a(.)(.*)/); // => ["abc", "b", "c"]

マッチしない場合は null を返す。マッチした場合は最初にマッチした部分の文字列を配列で返す。パターンにカッコを使った部分があれば配列の2つ目以降としてそれらの部分を返す。

このサイトは筆者(hydrocul)の個人メモの集合です。すべてのページは永遠に未完成です。