C#で正規表現でできるだけ短い文字列が一致するようにしたい

C#で正規表現でパターン.*のような任意の文字の繰り返しを使う場合で、できるだけ短い文字列でパターン一致させるようにしてみます。正規表現そのものについては、MSDNの.NET Framework の正規表現を参考にしてください。

正規表現で検索すると思ったより長い文字列にマッチしてしまう

例えば、下記のテキストから(1)の項目を抜き出したいとします。

(1) いろは
いろはにほへと
ちりぬるを
(2) 五十音
あいうえお
かきくけこ
(3) あるふぁべっと
ABC
DEF

行頭に括弧がある行が各項の区切りになってますので、(1)から\n(まで抽出して最後の1文字を取り除けばOKですね。と考えて、下記のコードにしたりします。

using System;
using System.Text.RegularExpressions;

namespace regex_trial3
{
    class Program
    {
        static void Main(string[] args)
        {
            string kotoba = @"(1) いろは
いろはにほへと
ちりぬるを
(2) 五十音
あいうえお
かきくけこ
(3) あるふぁべっと
ABC
DEF
";
            Match matchedObject = Regex.Match(kotoba, @"(^|\n)\(1\).*\n\(", RegexOptions.Singleline);
            Console.WriteLine(matchedObject.Value);
        }
    }
}

そうすると出力はこうなります。

(1) いろは
いろはにほへと
ちりぬるを
(2) 五十音
あいうえお
かきくけこ
(

余計なところまで付いてきてしまいました。検索するときに出来るだけ広い範囲でマッチするようになっているのですね。でも欲しいのは(1)項の部分だけです。ということで、限定子+?を使います。 検索パターンを変えてみました。

using System;
using System.Text.RegularExpressions;

namespace regex_trial3
{
    class Program
    {
        static void Main(string[] args)
        {
            string kotoba = @"(1) いろは
いろはにほへと
ちりぬるを
(2) 五十音
あいうえお
かきくけこ
(3) あるふぁべっと
ABC
DEF
";
            Match matchedObject = Regex.Match(kotoba, @"(^|\n)\(1\)([^\n]*\n)+?\(", RegexOptions.Singleline);
            Console.WriteLine(matchedObject.Value);
        }
    }
}

[^\n]*はラインフィード(改行)以外の文字で構成された文字列です。([^\n]*\n)+?\(とは、「\n以外で構成された文字列+\n」という文字列の1回以上の繰り返しが最小になる(までということです。 出力はこうなります。

(1) いろは
いろはにほへと
ちりぬるを
(

あとは最後の1文字を取り除けば、(1)の項目が取得できますね。 この投稿で試した環境は下記です。

  • Visual Studio 2015 Express for Windows Desktop (C#)

公開日

広告