西海岸より

つらつらざつざつと

正規表現のものぐさ(lazy, non-greedy)マッチング

忘れがちなのでメモ。
正規表現で?と言えば、一つ前の文字数が0回もしくは1回現れればマッチするもの。
だけど、*?、+?といったように書けば、最小となる文字列にマッチするようになり、ものぐさ、laze、non-greedyというそうな。

  • 以下が例。removeTagメソッドは、textから指定したtagを削除するというもの。
import java.util.regex.Pattern;

public class RemoveTag {
	public static String removeTag(String text, String tag) {
		return Pattern.compile("<" + tag + ">.*?</" + tag + ">").matcher(text).replaceAll("");
	}
	
	public static void main(String[] args) throws Exception {
		String result = removeTag("This is a <a>pen</a>. That is a <a>pencil</a>. This is it.", "a");
		System.out.println(result);
	}
}
  • 実行結果
This is a . That is a . This is it.

もし、以下のように?を取り除いて.*?を.*にすると

    return Pattern.compile("<" + tag + ">.*</" + tag + ">").matcher(text).replaceAll("");

以下のように結果が異なる。

This is a . This is it.

これは、?が無い場合には、最長の文字列にマッチし、.* の部分が以下の文字列にマッチして削除されてしまうため。

<a>pen</a>. That is a <a>pencil</a>