正規表現

エスケープシーケンスに対応する正規表現の考察

はじめに

この記事は、考察記事です。

バグがないように、気を付けてはいますが実用する場合は利用者の責任で実行してください。

前提条件
テストはJavascriptで行っています。
テストコードは、文字列自体のエスケープを含まないため、
" ' \ などはエスケープして実行してみてください。

何がしたいの

エスケープ文字列に対応する正規表現を考えます。
(正規表現内で必要なエスケープではありません)

sometext "match\"text\nmulti line \\\" backslash+quotation" 

みたいなテキストが渡されたときに、

"match\"text\nmulti line \\\" backslash+quotation"

みたいに抽出することを目的とします。

分かりやすさを優先するために、プログラム言語で必要なエスケープは無視します。

Javascriptで、正規表現内でバックスラッシュを表すためには

"\\\\" # -> "\\" 

と、文字列自体のバックスラッシュが必要ですが、ここでは無視します。
(バックスラッシュ4個で、1個のバックスラッシュを表している)

よくある解法

eval 系コマンドを利用

evalは使いません。
eval is evil です。

目的は、外部から渡された文字列から、エスケープされた文字列を抽出するのに、evalは危険すぎます。

最長マッチの利用

最長マッチを利用すると、見かけ上は正しく取れたように見えます。

".*"

これは、内部状態を正しく評価していないため、利用しません。

簡単な正規表現

例えば、""で囲まれた文字列を表現するために、私が使う簡易なコードは下記の正規表現です。

"[^\"]*"

これは、『ダブルクオーテーション以外の文字が0個以上連結して、ダブルクオーテーションで囲まれる』
文字列にマッチしますが、エスケープされた文字列を表せません。

最初の文字列でテストをすると、

"match\"

と出力されます。

今回考えた正規表現

今回、文字列を下記のように解釈しました。

  • 文字列ダブルクオーテーションで囲まれる。
  • プレーンテキストは、エスケープが必要な文字と、エスケープ文字を含まない。
  • エスケープ文字に続いて、エスケープが必要な文字が続く。

ここで
『プレーンテキストは、エスケープが必要な文字と、エスケープ文字を含まない。』
は、下記の正規表現となります。

[^'"\\]

また、
『エスケープ文字に続いて、エスケープが必要な文字が続く。』
は、下記正規表現で表せます。

\\["'\\\/bfnrt]

そのため、これから以下のように構成できると考えました。

"(?:[^'"\\]|\\["'\\\/bfnrt])*"

このコードは、現時点において正しく動いているように見えます。

検証が不十分のため、検証が終わるまでは考察として公開いたします。