[C#]正規表現 `System.Text.RegularExpressions.Regex`

System.Text.RegularExpressions.Regex クラスの使い方

メタ文字

正規表現の基本: .NET Tips: C#, VB.NET

文字クラス

  • . (改行は含まない-Singlelineオプションで任意の文字にマッチ)
  • \s (ECMAScriptオプション指定時は [ \f\n\r\t\v])
  • \S
  • \d
  • \D
  • \w (アンダースコアやひらがな、カタカナ、漢字などなどが含まれるので注意-ECMAScriptオプションで [a-zA-Z_0-9])
  • \W
  • \r
  • \n`
  • \t
  • \u0000
  • \x00
  • \b
  • \*
  • +
  • {n,m} {n} {n,}
  • ^ $
  • \A
  • \Z
  • \z
  • (?:) (?=) (?!) (?<=) (?<!) (?#)
  • \number $number $&(一致した部分全部)
  • (?<name>) \k<name> ${name}
    注意:見ればわかるように <~> も場合によりエスケープが必要
  • 文字クラス減算 [base_group-[excluded_group]]
    例) [a-z-[m]] : a-zからmだけ除く, [a-z-[d-w-[m-o]]] みたいにネストできる

正規表現にマッチするかどうかの判定

Regex regex = new Regex("HoGe", RegexOptions.IgnoreCase);
Debug.Write(regex.IsMatch("hOgE")); // True
string target = @"hogehoge";
Debug.Write(Regex.IsMatch(target, @"^(?:hoge){2}$")); // True;

正規表現にマッチした部分を取得

Regex regex = new Regex("(ABC)(?<foobar>DEF)");
Match match = regex.Match("ABCDEF");
GroupCollection groups = match.Groups;

Debug.WriteLine(match.Success); // True
Debug.WriteLine(match.Groups[0]); // ABCDEF
Debug.WriteLine(match.Groups[1]); // ABC
Debug.WriteLine(match.Groups[2]); // DEF
Debug.WriteLine(match.Groups["foobar"]); //DEF

if (match.Success)
{
  foreach (Group group in groups)
  {
    Debug.WriteLine(group.Value); // ABCDEF, ABC, DEF の順番で出力
  }
}

次のマッチを探す

Regex regex = new Regex(@"\w");
Match match = regex.Match("A-B-C");
do
{
  Debug.WriteLine(match.Value); // A, B, C の順に出力
  match = match.NextMatch();
} while (match.Success);

全てのマッチを取得する

Regex regex = new Regex(@"\w");
MatchCollection matches = regex.Matches("A-B-C");
foreach (Match match in matches)
{
  Debug.WriteLine(match.Value); // A, B, C の順に出力される
}

マッチした部分を置換

Match match = Regex.Match("foobar", "(foo)(?<xxx>bar)");

Debug.WriteLine(match.Result("@$0")); // @foobar
Debug.WriteLine(match.Result("@$1")); // @foo
Debug.WriteLine(match.Result("@$2")); // @$2
Debug.WriteLine(match.Result("@${xxx}")); // @bar

ドル記号 $&, $, $', $+, $_`

Match match = Regex.Match("foobar", "(o)(b)");

/* マッチした部分全体を出力 */
Debug.WriteLine(
  match.Result("$&")); // ob

/* マッチしなかった部分の前方 */
Debug.WriteLine(
  match.Result("$`")); // fo

/* マッチしなかった部分の後方 */
Debug.WriteLine(
  match.Result("$'")); // ar

/* 最後のGroup */
Debug.WriteLine(
  match.Result("$+")); // b

/* マッチ対象文字列全体 */
Debug.WriteLine(
  match.Result("$_")); // foobar

※ドル記号自体を出力したいときは $$ としてエスケープするのが無難

Regex.Split メソッド

string[] split = Regex.Split("***input***", "((in)(put))");
foreach (string str in split)
{
  Debug.WriteLine(str);
}

結果

***
input
in
put
***

コールバック置換

string result = Regex.Replace("foobar", "(foo)(?<xxx>bar)", delegate(Match match)
{
  string ret = "csharp-regular-expressions";
  foreach (Group group in match.Groups)
  {
    ret += "[" + group.Value + "]";
  }
  return ret;
});

Debug.Write(result); // csharp-regular-expressions[foobar][foo][bar]

メタ文字のエスケープ

Regex.Escapeメソッドを使う。

前方参照

何らかのフレーズに囲まれた部分にマッチさせたい場合とかに便利

Match match = Regex.Match("<div class="contents">でぃヴぃじょん</div>", @"<(div)>.+</\1>");
Debug.WriteLine(match); // <div class="contents">でぃヴぃじょん</div>

名前付きキャプチャの前方参照

\k<NAME> とする

Match match = Regex.Match("<div class="contents">でぃヴぃじょん</div>", @"<(?<NAME>div)>.+</\k<NAME>>");
Debug.WriteLine(match); // <div class="contents">でぃヴぃじょん</div>

肯定先読み

Debug.WriteLine(Regex.Match(
  "foobar", "foo(?=bar)")); // foo

Debug.WriteLine(Regex.IsMatch(
  "foobar", "foo(?=HOGE)")); // False

肯定後読み

Debug.WriteLine(Regex.Match(
  "foobar", "(?<=foo)bar")); // bar

Debug.WriteLine(Regex.IsMatch(
  "foobar", "(?<=HOGE)bar")); // False

否定先読み

Debug.WriteLine(Regex.IsMatch(
  "foobar", "foo(?!bar)")); // False

Debug.WriteLine(Regex.Match(
  "foobar", "foo(?!HOGE)")); // foo

否定後読み

Debug.WriteLine(Regex.IsMatch(
  "foobar", "(?<!foo)bar")); // False

Debug.WriteLine(Regex.Match(
  "foobar", "(?<!Hoge)bar")); // bar

オプション

RegexOptions 列挙体 (FlagsAttribute 属性付き)で指定

  • None : オプション無し
  • IgnoreCase : 大文字小文字の区別をしない
  • CultureInvariant : カルチャに依存しない。 IgnoreCase を使う場合はセットにして指定した方がいい気がする(正規表現のオプション)
  • Compiled : アセンブリにコンパイルして高速化する。ただし初期化に時間がかかる
  • Singleline : メタ文字のピリオドが任意の1文字にマッチさせる
  • ECMAScript : ECMAScript準拠の動作をする

RegexOptions.IgnorePatternWhitespace

パターン内の \s で表現可能な空白を無視する。空白を無視しない場合は "\s""\ " (半角スペース) を利用する。

Match match = Regex.Match(
  "AB",
  "A \t \r \n B",
  RegexOptions.IgnorePatternWhitespace);

Debug.WriteLine(match); // AB

コメントと RegexOptions.IgnorePatternWhitespace

(?# ) でコメント。 IgnorePatternWhitespace オプションが付いてる場合は # から 行末 までコメント

Match match = Regex.Match("foobar", "(foo)(?#bar)");

Debug.WriteLine(match); // foo
Match match = Regex.Match("foobar", "(foo)#bar", RegexOptions.IgnorePatternWhitespace);

Debug.WriteLine(match); // foo
Match match = Regex.Match("foobar", "(foo)#bar");

Debug.WriteLine(match.Success); // False

RegexOptions.ExplicitCapture

(?<name> ) だけキャプチャするオプション

Match match = Regex.Match("input", "(in)(?<NAME>put)", RegexOptions.ExplicitCapture);
foreach (Group group in match.Groups)
{
  Debug.WriteLine(group.Value);
}

結果

input
put

RegexOptions.RightToLeft

MatchCollection matches = Regex.Matches("AB DE", @"\w+", RegexOptions.RightToLeft);
foreach (Match match in matches)
{
  Debug.WriteLine(match.Value);
}

結果

DE
AB

RegexOptions.Multiline

このオプションを指定すると ^$ の意味が変わる。

  • ^ : 行の先頭に一致する
  • $ : \n または 入力文字の末尾 に一致する (\r には一致しない!)

    string pattern = "(^.+)$";
    string input = "A\nB\nC";
    Debug.WriteLine(Regex.IsMatch(input, pattern)); // False
    
    foreach (Match match in Regex.Matches(input, pattern, RegexOptions.Multiline))
    {
    Debug.WriteLine(match.Groups[1]); // A, B, C の順に出力される
    }
    
    string pattern = "(^.+)$";
    string input = "A\rB\r\nC";
    Debug.WriteLine(Regex.IsMatch(input, pattern)); // False
    
    MatchCollection matches = Regex.Matches(input, pattern, RegexOptions.Multiline);
    Debug.WriteLine(
    matches[0].Groups[1]); // A\rB\r\n
    Debug.WriteLine(
    matches[1].Groups[1]); // C
    

インラインオプション

// インラインオプションでオプションを一部分で有効化
Debug.WriteLine(
  Regex.IsMatch("Input", "(?i:INPUT)")); // True
// インラインオプションでオプションを一部分で無効化
Debug.WriteLine(
  Regex.IsMatch("Input", "(?-i:INPUT)", RegexOptions.IgnoreCase)); // False

上記のものは (?オプション-オプション: ) で複合も可能

使用可能なオプションは imsnx

  • i : RegexOptions.IgnoreCase
  • m : RegexOptions.Multiline
  • s : RegexOptions.Singleline
  • n : RegexOptions.ExplicitCapture
  • x : RegexOptions.IgnorePatternWhitespace
Share
関連記事