正規表現のエスケープが必要な文字:14 文字の一覧
1.5 をそのまま正規表現に埋め込むと、ピリオドが任意の 1 文字に一致し、1X5 や 1a5 まで拾ってしまいます。エスケープは、特別な意味を持つ文字の前にバックスラッシュを付け、その文字自身だけを表すようにする操作です。
エスケープが必須になる場面
検索欄、ログの絞り込み、一括リネームは、いずれも入力を普通の文字として扱いたい場面です。ピリオド、アスタリスク、括弧、角括弧が入力に含まれていると、エスケープしない限り一致の意味が変わり、無関係な行を大量に拾うか、構文エラーで例外になります。
ファイル名、URL、バージョン番号をパターンにする場合も同じです。1.2.3 のピリオド、a+b のプラス、[下書き] の角括弧は、エスケープしないと 1.2.3 が 1x2y3 にも一致してしまいます。
- 検索欄の入力を正規表現に組み込む
- ファイル名やバージョンを文字列として一致させる
- 記号を含む文字列をログから探す
- 読みやすいパターンを設定ファイルに書く
対象は次の 14 文字
ピリオド、アスタリスク、プラス、疑問符、キャレット、ドル記号、左右の中括弧、左右の丸括弧、縦棒、左右の角括弧、そしてバックスラッシュ自身で、合計 14 文字です。いずれも正規表現で特別な意味を持ち、直前にバックスラッシュを置くと文字そのものを表します。
それ以外は変更しません。ハイフン、スラッシュ、空白、英字、数字にはバックスラッシュを付けません。すべての文字をエスケープするより短く読みやすくなります。ただし角括弧の文字クラスに入れる場合、中央のハイフンは依然として意味を持つため別途対応が必要です。
- 対象は 14 文字:. * + ? ^ $ { } ( ) | [ ] \
- ハイフンとスラッシュはエスケープしない
- 空白、英字、数字はそのまま
- 文字クラス内のハイフンは個別に処理する
パターンに組み込むときの 2 つの落とし穴
1 つ目は二重エスケープです。バックスラッシュ自身も対象なので、すでにエスケープ済みの文字列をもう一度処理するとバックスラッシュが 2 つになり、「バックスラッシュ + その文字」を探すパターンになって、目的の文字に一致しなくなります。
2 つ目は言語側の文字列エスケープです。Java では 2 つ書いて正規表現の 1 つになり、Python の通常文字列も同じです。raw 文字列を使えばこの層を省けます。ツールが扱うのは正規表現の層だけで、言語の文字列層は自分で補う必要があります。
- 二重エスケープをしない(バックスラッシュが増える)
- Java や Python では文字列層がもう 1 つ必要
- Python は raw 文字列で 2 層目を避けられる
- 組み込んだら既知のテスト文字列で確認する
よくある質問
どの文字をエスケープする必要がありますか?
ピリオド、アスタリスク、プラス、疑問符、キャレット、ドル記号、中括弧、丸括弧、縦棒、角括弧、そしてバックスラッシュ自身の 14 文字です。ハイフンとスラッシュは対象外で、ツールは何も付けません。
エスケープしてもバックスラッシュが残るのはなぜですか?
バックスラッシュは「次の文字を文字そのものとして扱う」という指示なので、残す必要があります。コードに書くときは、言語がバックスラッシュを解釈する分をもう 1 層加えます。Java の文字列では 2 つ書きます。
re.escape や RegExp.escape をそのまま使えますか?
使えます。目的は同じで、特殊な文字を文字列として扱えるようにします。対象の文字集合は実装によって少し異なり、空白やハイフンもエスケープする場合があるため、言語をまたぐときは実際の出力で確認してください。
関連ツール:正規表現のエスケープ