正規表現は単一の言語ではありません。POSIX BRE、POSIX ERE、Perl 互換エンジンには 共通部分がありますが、構文、マッチング規則、利用可能な機能が異なります。
POSIX BRE #
基本正規表現は、grep と sed で使用されてきた歴史的な構文です。
重要な規則は次のとおりです。
- グループ化には
\(と\)を使用します。 - 回数指定の繰り返しには
\{m,n\}を使用します。 - ツールが拡張機能を追加していない限り、
+、?、|、()はリテラル文字です。 - 後方参照には
\1、\2などを使用します。
BRE は移植性がありますが、多くのメタ文字をエスケープする必要があるため冗長です。
POSIX ERE #
拡張正規表現は、現代的な正規表現の構文に近い形式です。
()はグループ化します。+は 1 回以上を意味します。?は 0 回または 1 回を意味します。{m,n}は繰り返し回数を指定します。|は選択を表します。
grep -E と sed -E はこの形式を使用します。POSIX ERE は、遅延量指定子、
先読み、後読みをサポートしないため、機能が制限されています。
Perl 互換エンジン #
Perl 互換正規表現には、POSIX RE にない機能が追加されています。
*?や+?などの遅延量指定子- 先読みと後読み
(?:...)などの非キャプチャグループ- 多くのエンジンで利用できる名前付きキャプチャ
- より豊富な文字クラス構文
したがって、非貪欲マッチを行うには、多くの場合エンジンを切り替える必要があります。 POSIX BRE と ERE には、同等の演算子が存在しません。
マッチング動作 #
POSIX エンジンは、左端最長一致に基づいて定義されています。その規則により、 構文が似ている場合でも Perl 形式のエンジンとは異なる結果になることがあります。
選択と繰り返しが重なる場合、エンジンは最初に成功した構文上の選択肢ではなく、 より長い一致を優先する可能性があるため、この違いが重要になります。
アンカーもエンジンとモードに依存します。POSIX の ^ と $ は文字列の先頭と
末尾を表し、行に対する動作はツールごとに異なります。PCRE 形式のエンジンには、
絶対的な文字列境界用のアンカーと複数行モードが別に用意されていることがあります。
コマンドのデフォルトに依存せず、入力のリテラルな境界を明示的にマッチさせてください。
文字クラスは固定された ASCII の略記ではありません。[[:alpha:]] などの POSIX
ブラケットクラスは有効なロケールに従います。一方、\w、大文字と小文字の同一視、
Unicode プロパティは、Perl 互換の実装やフラグによって異なります。バイト単位の
自動処理では既知のロケールを設定するか、エンジンの Unicode モードを意図的に
選択してください。
バックトラッキングエンジンでは、長い不一致入力に対する (a+)+$ のような、
曖昧な入れ子の繰り返しによって実行時間が指数関数的に増加する可能性があります。
信頼できないデータをパターンで処理する場合は、入力サイズを制限し、重複する選択肢や
入れ子の量指定子を避けるか、線形時間で動作するエンジンを使用してください。
先読み、後読み、非キャプチャグループは式の構造を改善しますが、エンジン間の互換性を
もたらすものではありません。
実用的な変換 #
同じ意図でも、異なる構文が必要になる場合があります。
- キャプチャグループ: BRE では
\(...\)、ERE では(...) - 1 桁以上の数字: BRE では
\{1,\}、ERE では+ - 非貪欲ワイルドカード: POSIX RE では利用不可
移植性が重要な場合は、特定のエンジンを選択し、要件を満たす最小限の機能セットを 使用してください。バックスラッシュを機械的に追加または削除するのではなく、 意図する言語とマッチングセマンティクスに基づいて変換してください。
コメント
GitHub で閲覧・コメントする(投稿にはログインが必要です)