正規表現でパターンマッチには含めたいが、読み込み済みにはさせたくない場合の記述方法

正規表現でパターンマッチには含めたいが、読み込み済みにはさせたくない場合の記述方法を紹介します。

概要

正規表現のパターンマッチでマッチさせるパターンには含めたいが、その部分は読み込み済みにさせたくない場合があります。処理済みにさせない場合は正規表現の ?= 演算子を利用します。
補足
正規表現の「肯定先読み」の動作の詳細についてはこちらの記事を参照してください。

具体例

正規表現でパターンマッチには含めたいが、読み込み済みにはさせたくない場合の具体例を紹介します。

UI

下図のUIを作成します。テキストボックスを3つボタンを1つ配置します。

コード

下記のコードを記述します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;

namespace RegExDemo
{
  public partial class FormMultiMatch : Form
  {
    public FormMultiMatch()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      string input = textBox1.Text;
      string pattern = textBox2.Text;

      Regex reg = new Regex(pattern);
      Match match = reg.Match(input);
      while (match.Success == true) {
        textBox3.Text += match.Value +"\r\n";
        match = match.NextMatch();
      }
    }
  }
}

解説

上部のテキストボックス、textBox1に入力された文字列を入力とし、textBox2に入力された文字列を正規表現のパターンマッチ式とします。マッチ処理を実施しすべてのマッチした部分のマッチ文字列を下部のテキストボックス(textBox3)に表示します。

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。


テキストボックスに下記を入力します。
入力文字列
/abc/def/ghi/jkl/mno/pqr/stu
パターンマッチ正規表現式
/[a-z]*/



[button1]をクリックします。下部のテキストボックスに下記の値が表示されます。
/abc/
/ghi/
/mno/



実行結果の解説

"/[a-z]*/"の席表現式により、両側を「/」で挟まれたアルファベットの文字にマッチします。今回の入力文字列"/abc/def/ghi/jkl/mno/pqr/stu"では、最初に "/abc/"の部分にマッチします。次の処理では、"/abc/"がマッチしたため、その次の文字"d"から処理が始まります。"def/ghi/jkl/mno/pqr/stu"の文字列の入力と同等のため、"/ghi/"の部分にマッチします。同様に次の処理はマッチした次の文字"j"から始まるため、"/mno/"にマッチし、その後はマッチするパターンは無く処理の終了となります。

この例で、「/」で両側を挟まれたすべての文字列を抽出するには、両側を「/」で挟まれた文字列にはマッチさせるが、末尾の右側の「/」は読み込み済み、または処理済みにはならず、次の処理は「/」から処理を開始すれば、すべての両側を「/」で挟まれた文字列を抽出できます。パターンには右側の「/」を含みたいが読み込み済みとしては処理したくない動作としたいです。

パターンマッチの正規表現式の記述

上記の動作を実現するため、?= 演算子を用い、下記の正規表現の式を記述します。

先のプログラムにて、テキストボックスに下記を入力します。
入力文字列
/abc/def/ghi/jkl/mno/pqr/stu
パターンマッチ正規表現式
/[a-z]*(?=/)

(?=)を用いて、右側の「/」をグループ化します。?=を指定したグループは肯定先読みの処理が実行され、グループ内の文字列を含めてマッチ判定をします。ただし、マッチした場合に(?=)のグループの文字列はマッチした文字列として取得されません。またグループの文字列は読み込み済みとはならず、?=を指定したグループの手前までが処理済みの文字列の判定になります。

実行結果

[button1]をクリックします。下記の結果が下部のテキストボックスに表示されます。
/abc
/def
/ghi
/jkl
/mno
/pqr

両側が「/」で挟まれた英文字がすべて取得できていることが確認できます。?=演算子を利用したため、マッチした文字列には右側の「/」は含まれていないことが確認できます。

著者
iPentec.com の代表。ハードウェア、サーバー投資、管理などを担当。
Office 365やデータベースの記事なども担当。
最終更新日: 2024-01-06
作成日: 2018-01-10
iPentec all rights reserverd.