C#の正規表現の扱いはJavaよりイイ!
以下のような文字列があったとする。
私の名前は${name}です。年齢は${age}です。
${}で囲まれている中の文字を取り出すプログラムを作りたい。このプログラムの場合の期待値は「name」「age」である。
ベースとなるプログラムはこんな感じ。
string target = "私の名前は${name}です。年齢は${age}です。"; MatchCollection matches = new Regex("\\$\\{.*\\}").Matches(target); foreach (Match match in matches) { Console.WriteLine(match.Value); }
しかしこれだと実行結果は、次のようになる。
${name}です。年齢は${age}
こうなる理由としては、正規表現のパターンマッチングが最長一致として動作しているため。なので最短一致にすればいい。そのため正規表現パターンをこのように変える。
"\\$\\{.*?\\}"
「?」を追加するだけ。こうすることで実行結果は以下のようになる。
${name} ${age}
近づいてきた♪
あとは${}のなかの部分だけ抽出すればOK!ただし、ここで以下のようにSubString使ってやってもできるけど、エレガントじゃない。泥臭すぎる。
match.Value.Substring("${".Length, value.IndexOf("}") - ("${".Length));
もっとエレガントにできるのが正規表現なのだ。ということで、最終的なプログラムは以下です。
string target = "私の名前は${name}です。年齢は${age}です。"; MatchCollection matches = new Regex("\\$\\{(?<1>.*?)\\}").Matches(target); foreach (Match match in matches) { Console.WriteLine(match.Groups[1].Value); }
抽出したい部分を(?<1>)で囲むとMatchオブジェクトのGroupから取得できます。別に1じゃなくても2でも動きます。ただし0だとうまくいきませんでした。
ところでJavaでこれと同等のことってできるんでしょうか?知っている人がいたら教えて下さい!
参考
他の言語の正規表現による抽出方法は以下をどうぞ。C#よりずっと簡単♪
■ruby
http://d.hatena.ne.jp/mtoyoshi/20080630
10/5追記
■「Javaの正規表現の扱いはC#よりイイ!」を書きました。
http://d.hatena.ne.jp/mtoyoshi/20081005