コンテンツにスキップ

正規表現の書き方

Category: 正規表現

ssu の regex_ で始まる関数(regex_match regex_find regex_findall regex_count regex_replace regex_replace_first regex_erase regex_erase_first regex_split regex_escape)に共通する、パターン・オプション・結果の取り出し方をまとめます。Mc203-1以降。

正規表現エンジンは uka_regexp(伺か共用の正規表現エンジン)です。PCRE2(Perl 互換)に近い書式で、\d \w \s、[a-z]、* + ? {n,m}(? を付けると最短一致)、|、(...)、(?:...)、(?<名前>...)、\1、^ $ \b、先読み・後読み((?=...) (?!...) (?<=...) (?<!...))などが使えます。文字は Unicode のまま扱うので、ひらがな・漢字も 1 文字として一致します(. や [^a] など)。ただし \w \d \s と \b は ASCII の範囲だけが対象で、(regex_match、日本語、^\w+$) は 0 です。日本語の範囲は [ぁ-ん] [ァ-ヶ] [一-龠] のように書きます。

里々の中で書くときの注意

パターンの中の \ や半角の ( ) はそのまま書けます。全角の ( ) は里々の記法として先に解釈されるので、文字として使いたいときは φ( φ) と書きます(前処理)。、 は引数の区切りになります。

オプション

関数の最後の引数(省略可)に、次の文字を並べて指定します。大文字でも同じです。空白と , は無視されます。

文字 意味
i 大文字小文字を区別しない
s . が改行にも一致する
m ^ と $ が行頭・行末に一致する(指定しないと文字列の先頭・末尾)
x パターン中の空白とコメント(# から行末まで)を無視する

それ以外の文字を書くと 正規表現のオプションが正しくありません(i, s, m, x が使えます)。(エラー)になります。

パターンの中で (?i) (?s) (?m) と書いても指定できます。(?i) はそこから後ろに効きます(A(?i)B は A を区別して、B は区別しません)。

グループの番号

一致した部分は、(S0) が全体、(S1) 以降が括弧のグループです(regex_match、regex_find で入ります)。番号は開き括弧の順です。

名前付きグループ (?<名前>...) も、名前の付かないグループと同じく開き括弧の順に番号が付きます(PCRE2 と同じ)。(?<w>\w+) (\w+) では、(S1) が w、(S2) が 2 つめの (\w+) です。番号に頼らず ${名前} で参照するほうが安全です。

名前を使ったサブルーチン呼び出し(次の節)で名前から取り込んだパターンのグループは、(S1) 以降には入りません。

置換後の書き方

regex_replace などの「置換後」で使えます。

書き方 意味
$1 $2… その番号のグループ
${名前} 名前付きグループ
$& 一致した部分全体
$` 一致した部分より前
$' 一致した部分より後ろ
$_ 対象の文字列全体
$$ $ 自身

パターンの中から里々の名前を呼ぶ(サブルーチン呼び出し)

Mc205-3以降。パターンの中で、そのパターンに書かれていない名前のサブルーチン呼び出し (?&名前) (?P>名前) \g<名前> \g'名前' を書くと、(名前) を展開した結果がパターンとして取り込まれます。名前は、(名前) と同じ順(SAORI・内蔵関数 → 単語群 → 文 → 変数 → 内蔵変数)で探されます。

@年月
\d{4}_\d{2}

*OnTest
:(regex_match、2026_10、^(?&年月)$)

この例では ^(?&年月)$ の (?&年月) が、単語群 @年月 から選ばれた \d{4}_\d{2} になり、結果は 1 です。変数でも同じです(タブ区切りの代入 $year<タブ>\d{4} と書いておき、(?&year) で呼ぶ)。取り込んだパターンの中で、さらに別の名前を呼んでもかまいません。

  • 名前が (名前) として展開できないとき(どこにも無いとき)は、書式のエラーになります(正規表現の書式が正しくありません(undefined subroutine '名前')。)。
  • パターンに (?<名前>...) や (?P<名前>...) が書かれているときは、そちらが先に使われます。
  • 取り込むたびに (名前) が展開されます。単語群はそのたびにランダムに選ばれ、(名前) の中に副作用のある関数があれば実行されます。
  • 展開は里々本体の中でだけ行われます。単体の ssu.dll から呼んだときは、名前はすべて未定義として扱われます。
  • $year=\d{4} のように = で代入すると値が式として計算されるので、パターンによっては計算できずにエラーになります($two=(?&year)_(?&mon) など)。パターンを入れる変数は、タブで区切る代入($year<タブ>\d{4}。<タブ> はタブ文字)で書くと確実です。

注意

  • 正規表現の書式の誤り(閉じていない括弧、未定義の名前を呼んだときなど)は、正規表現の書式が正しくありません(…)。 というエラー文になります(Mc205-3以降。それより前は報告されず、エンジンが解釈できる範囲で解釈されていました)。
  • 一致の探索の途中でバックトラックの回数が上限を超えると、正規表現の照合に時間がかかりすぎたので打ち切りました。 というエラー文になります(Mc205-3以降)。
  • 空文字列に一致するパターンでも、1 文字ずつ進むので止まらなくなることはありません((regex_count、abc、) は 4)。
  • 複雑なパターンで一致の探索に時間がかかることがあります(入れ子の * など)。外部から来た文字列をパターンにするときは、regex_escape を通してください。