正規表現の括弧のグルーピングにマッチした文字列を取得するには (group)

正規表現の中にカッコで括られた部分がある場合は、そのカッコの中にマッチした部分だけを取り出す機能があるが、以下は各プログラミング言語別のその方法のメモ。

Java

import java.util.regex.Matcher;
import java.util.regex.Pattern;

Matcher matcher = Pattern.compile("dear\\s+(\\S+)").matcher("Happy birthday dear Ken");
if (matcher.find()) {
  System.out.println(matcher.group(1));
}

Scala

val Pattern = ".*dear\\s+(\\S+).*".r;
"Happy birthday dear Ken" match {
  case Pattern(name) => println(name);
  case _ => println("Unmatch!");
}

PHP

if (preg_match('/dear\s+(\S+)/', "Happy birthday dear Ken", $matches)) {
    echo $matches[1];
}

Python

m = re.compile("dear\\s+(\\S+)").search("Happy birthday dear Ken");
if m:
    print(m.group(1))

Ruby

if "Happy birthday dear Ken" =~ /dear\s+(\S+)/
  puts $1
end

Perl

if ("Happy birthday dear Ken" =~ /dear\s+(\S+)/) {
    print "$1\n";
}

関連

Java

正規表現をコンパイルして java.util.regex.Pattern インスタンスを生成し、その matcher メソッドに文字列を渡すことで java.util.regex.Matcher インスタンスを取得し、その後は、find メソッドを呼び出すごとに部分マッチングするので、マッチングした後に group メソッドで括弧にマッチングした文字列を取得できる。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {

    public static void main(String[] args) {
        Matcher matcher = Pattern.compile("dear\\s+(\\S+)").matcher("Happy birthday dear Ken");
        if (matcher.find()) {
          System.out.println(matcher.group(1));
        }
    }

}

Scala

正規表現のパターンを予め大文字で始まる名前の変数に入れておき、 match式を使って、パターンマッチングする。

val str = "bcccdef";
val Pattern = ".*b(c+).*".r;
str match {
    case Pattern(s) => println(s);
    case _ => println("Unmatch!");
}
// 出力結果
// ccc

パターンマッチングは文字列全体とマッチするかどうかを判定するので、 "b(c+)".r と書いてもこの場合はマッチしない。

PHP

preg_match という関数に3つ目の引数を渡すと、3つ目の引数に配列で保存してくれる。

if (preg_match('/dear\s+(\S+)/', "Happy birthday dear Ken", $matches)) {
    echo $matches[1];
}

$matches[0] には正規表現全体にマッチした文字列が入り、 $matches[1] には1つ目の括弧にマッチした文字列が入り、 $matches[2] には2つ目の括弧にマッチした文字列が入る、という具合である。

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

Python

正規表現オブジェクトのmatchメソッドまたはsearchメソッドの返り値に対して、groupメソッドを呼び出すと、グルーピングにマッチした文字列を取得できる。

r = re.compile("b(c+)")
m = r.match("bcccdef")
if m:
    print(m.group(1))
    # => ccc
match(str)
文字列の先頭がマッチするかどうかを判定し、マッチしたら MatchObject インスタンスを返し、マッチしなかったら None を返す
search(str)
文字列の先頭に限らずマッチするかどうかを判定し、マッチしたら MatchObject インスタンスを返し、マッチしなかったら None を返す

Ruby / JRuby

正規表現にマッチさせると、 Regexp.last_match または $~ という名前で正規表現全体やグルーピングにマッチした文字列を取得できる。または $1, $2, $3, … でグルーピングにマッチした文字列を取得できる。これらの変数はスコープごとに別々である。

str = "abcabcc"
if str =~ /b(c(de?))/
    p Regexp.last_match[0] # => "bcd"
    p $~[0]                # => "bcd"
    p Regexp.last_match[1] # => "cd"
    p $~[1]                # => "cd"
    p $1                   # => "cd"
    p Regexp.last_match[2] # => "d"
    p $~[2]                # => "d"
    p $2                   # => "d"
end

String#scan というメソッドを使うと、文字列の中でマッチするすべての箇所についてグルーピングにマッチした文字列を配列の配列で取得できる。

str = "abcabcc"
p str.scan(/b(c(de?))/)    # => [["cd", "d"], ["cde", "de"]]

Perl

正規表現に掛けると $1, $2, $3, … にグルーピングにマッチした文字列が入る。

$0 は実行されているPerlスクリプトファイル名が入っていて、正規表現とは関係ないので注意。

マッチした文字列全体は [$&] という変数で参照できる。ただし、Perl 5.20 よりも古いバージョンの場合、この変数を参照している箇所が1箇所でもあると、スクリプト全体の正規表現処理のスピードが落ちるらしい。 Perl 5.10 以上であれば、${^MATCH} という変数を使うと速度低下は免れるが、 /p という修飾子を付ける必要がある。

$`, ${^PREMATCH}
マッチした文字列より前の部分
$&, ${^MATCH}
マッチした文字列全体
$', ${^POSTMATCH}
マッチした文字列より後ろの部分

my $str = "bcccdef";

if ($str =~ /b(c+)/p) {
    print "$1\n";
    # => ccc

    print "${^POSTMATCH}\n";
    # => def
}

sh (シェルスクリプト)

sedコマンドで正規表現による置換ができるが、 ()でのグルーピングを参照するには $1, $2, $3 などではなく、\1, \2, \3 を使う。

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