2

AKA正規表現でエスケープされていない文字シーケンスを見つけるにはどうすればよいですか?

以下の環境が設定されているとします。

@secret = "OH NO!"
$secret = "OH NO!"
@@secret = "OH NO!"

そして、次のようなファイルから読み込まれた特定の文字列:

some_str = '"\"#{:NOT&&:very}\" bad. \u262E\n#@secret \\#$secret \\\\#@@secret"'

これを Ruby 文字列として評価したいのですが、補間は行いません。したがって、結果は次のようになります。

puts safe_eval(some_str)
#=> "#{:NOT&&:very}" bad. ☮
#=> #@secret #$secret \#@@secret

対照的に、eval-only ソリューションでは、

puts eval(some_str)
#=> "very" bad. ☮
#=> OH NO! #$secret \OH NO!

最初に私は試しました:

def safe_eval(str)
  eval str.gsub(/#(?=[{@$])/,'\\#')
end

しかし、これは上記の悪意のある中間ケースでは失敗し、次のようになります。

#=> "#{:NOT&&:very}" bad. ☮
#=> #@secret \OH NO! \#@@secret
4

2 に答える 2

1

エスケープする文字の前に偶数個のバックスラッシュがあることを確認することにより、正規表現を介してこれを行うことができます。

def safe_eval(str)
  eval str.gsub( /([^\\](?:\\\\)*)#(?=[{@$])/, '\1\#' )
end

…つまり:

  • バックスラッシュではない文字を見つける[^\\]
  • 2 つのバックスラッシュが続く(?:\\\\)
    • 0回以上繰り返される*
  • その後にリテラル#文字が続く
  • {その後、 、@、または$文字が表示されることを確認します。
  • そしてそれを
    • 偶数個のバックスラッシュが続く非バックスラッシュ
    • バックスラッシュと#
于 2013-05-22T15:32:44.067 に答える