正規表現を使った完全一致について 1


Beta 3 には正規表現を使って文字列全体の一致を調べる機能「正規表現の完全一致」が実装されました。

CF25 のエクステンションとしてはデータ形式の一致検索と同時にデータの抽出・加工が可能になっている点で Regex Partial Match や Regex Replace とは活用方法が異なります。

単純な文字列マッチとして利用される前提では設計されておらず、正規表現を利用しない、あるいはサブマッチ要素を2つ以上含まない正規表現の利用は推奨していません。

ここでは機能の具体的な使い方などについて説明していきます。


正規表現のキャプチャグループと利用できる表現について

正規表現を使った完全一致では「キャプチャグループ ( Capturing Groups )」という概念を利用します。

キャプチャグループは「グループ化/捕捉グループ」とも訳されますが難しく考える必要は無く、正規表現を丸括弧「()」使って括る=文字列の中に括弧を使った範囲指定で「グループ」を(作る)だけです。

Capturing Groups は「JavaScript」「.NET」「C++ std::regex ECMAScript」など三つの言語間で主要機能では共通化されています。ただし互換性は完全では無く現時点では上記三つの中だと .NET が正規表現の機能的充実が一番高い環境になってますが、正規表現に関するドキュメントを探す場合 C++ 以外に .NET や JavaScript 用でもある程度役に立ちます。

Named capturing group や Conditional、Lookbehind は C++17 std::regex ECMAScript が全く対応してないので注意が必要。

  • x|y >> The alternation operator
  • [xyz] >> 文字集合
  • [^xyz] >> 文字集合の否定
  • \n >> Backtracking Into Capturing Groups
  • (x) >> Capturing Groups
  • {n} >> Fixed quantifier
  • {n,m} >> Greedy quantifier
  • {n,} >> Greedy quantifier
  • (?:x) >> Non-Capturing Groups
  • (?=x) >> Positive lookahead
  • (?!x) >> Negative lookahead

筆者も全部は試していませんが、std::regex ECMAScript の Capturing Groups で上記は利用できる表現になっています。

正規表現を利用した完全一致検索の実例

国際規格 ISO 8601:2019 フォーマットを利用して正規表現の完全一致とその活用例を紹介します。

国際規格 ISO 8601 というフォーマットは日付・時刻の記述順を標準化し表記するための仕様で、ISO 8601:2019 は一番最新の拡張されたフォーマットです。

ISO 8601:2019 の基本形

yyyy-mm-ddTHH:MM:SSZ

フォーマットの基本形は上記、実際のデータは

2022-08-22T17:46:51Z

これが「年月日時分秒」を示す国際データフォーマットを利用した実例。日付・時刻を「 T 記号」で二つに分類、データ終端にある Z は「タイムゾーン指定子」。タイムゾーン指定子は上の例だと協定世界時(UTC)を意味し、データとして時差が必要な場合は日本なら +09:00 と書きます。

2022-08-22T17:46:51+09:00

日本は UTC よりも9時間差があるためタイムゾーン指定子は Z の代わりに +09:00 を記述すれば協定世界時 (UTC+9) もしくは日本標準時 (JST) になります。今回は例として「2022-08-22T17:46:51Z」(UTC) の方を活用します。これを正規表現で完全一致させる一例として以下のように記述できます。

(^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)Z$)

文字列全体を検索の対象とするため行頭「^」と行末「$」を含めて丸括弧で囲い、その内部に (\d+) とキャプチャグループ化してあります。この完全一致だと得られるサブマッチは 6 つ、

2022” “08” “22” “17” “46” “51” というサブマッチ文字列を得られます。

キャプチャグループの入れ子

サブマッチの中にサブマッチを含めた「入れ子」も正規表現で記述できます。すこし読み取りにくいかもしれませんが

((^.+)T((\d+):(\d+):(\d+))Z$)

上記の場合、「日付」「時刻」で二分割したグループを作り「時刻」のグループから3つの要素をキャプチャしています。すると

2022-08-22” “17:46:51” “17” “46” “51” と5つの要素が得られます。

サブマッチは配列要素のように値を受け取ることができる

完全一致した場合、丸括弧で囲まれた各グループが「サブマッチ要素」としてエクステンションに記録されています。記録されたサブマッチは配列のようにインデックスを指定して値を CF25 の Expression から文字列を受け取ることができます。

以下は CF25 の Expression を利用した実例

"YY-MM-DD = " + RGX_SubMatch$( "RGX", 0 ) + "年" + RGX_SubMatch$( "RGX", 1 ) + "月" + RGX_SubMatch$( "RGX", 2 ) + "日"

あるいは大量のサブマッチ要素を得た場合、CF25 はループ処理に「高速ループ(fast loop)」を利用してサブマッチ要素を受け取るイベントを作るのですが、「スマートデリミタ機能」を使えばエクステンションが自動的にデリミタを選択してサブマッチ要素を結合した結果を返します。

スマートデリミタ機能とは

スマートデリミタはサブマッチ要素数に一致した文字列数でエクステンションにあらかじめデリミタとして利用したい文字列を与え、正規表現を使った文字列抽出と加工・再構築をエクステンション側で自動処理する機能です。

基本は「サブマッチ要素数 == 文字列数」と数を揃えてデリミタに利用したい文字列をエクステへ送信して使います。例えば ISO 8601 形式データのデリミタを「年月日時分秒」に置き換えた処理結果が自動で得られます。

2022-08-22T17:46:51Z” >> “2022年08月22日17時46分51秒

データを加工するイベントを作る作業が省略され、エクステンションがループ処理を代行するため高速に処理できるメリットがあります。スマートデリミタはデリミタとして与えられた文字列の文字列長とサブマッチ要素数を比較しながら自動実行する処理の内容を自動で選択します。

  • スマートデリミタとして送信された文字列が0文字(NULL)の場合は、自動化処理は実行されません。サブマッチ要素はエクステンションに保持されているので CF25 でイベントを作って値を取り出してください。
  • スマートデリミタとして送信された文字列が1文字の場合は、すべてのサブマッチ要素の結合に指定されたデリミタ1文字を利用します。
  • スマートデリミタとして送信された文字列が2文字の場合は、サブマッチ要素の結合に指定された文字列の1文字目をデリミタとして利用し、一番最後のサブマッチ要素に2文字目のデリミタを利用します。
  • スマートデリミタの実例

    デリミタ( Delimiter )は列挙されたデータ項目の区切りを表す「区切り文字」のこと、CSV や JSON 形式など多くのデータ形式で利用されている「,(カンマ区切り)」が代表例。ISO-8601 では年月日に「-」、時分秒に「:」をそれぞれデリミタとして使うことが指定されていて、更に年月日と時分秒を区切る「T 記号」と「タイムゾーン指定子 Z」が用いられます。

    「2022-08-22T17:46:51Z」という文字列は正規表現を使って

    (^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)Z$)

    で完全一致を検索できますが、スマートデリミタとして指定された文字列「年月日時分秒」を使えば戻り値では「2022年08月22日17時46分51秒」という文字列を一発で得られます。

    上記例だとスマートデリミタに「,」を1文字与えれば戻り値は「2022,08,22,17,46,51,」となる。

    スマートデリミタに「,;」と2文字あたえると「2022,08,22,17,46,51;」終端処理は二文字目が利用されます。

    サブマッチが 6 つでスマートデリミタの文字数が3文字の場合、4つ目以降のデータをスキップして文字列処理を完了する。>>「2022年08月22日」

    スマートデリミタは与えられた文字列数に応じて処理が変わり、データ加工のために回すループ処理の自動化をサポートする機能としてデザインされています。


    Leave a comment

    メールアドレスが公開されることはありません。 が付いている欄は必須項目です

    One thought on “正規表現を使った完全一致について