检查字符串是否已转义

时间:2014-11-10 15:07:34

标签: ruby

我有3个字符串:

#1 アンジェリーナ・ジョリー
#2 %E3%82%A2%E3%83%B3%E3%82%B8%E3%82%A7%E3%83%AA%E3%83%BC%E3%83%8A%E3%83%BB%E3%82%B8%E3%83%A7%E3%83%AA%E3%83%BC
#3 Angelina_Jolie
  1. 如何识别其他字符串中的#2,换句话说,如何检查方法CGI.escape(来自Ruby或任何其他执行相同操作的方法)是否已应用于给定字符串?
  2. 如何轻松检查字符串应该或可以转义,换句话说,如果将CGI.escape应用于字符串,结果将会与原始字符串不同?在这种情况下,#1可以转义,而#3则不转义。

3 个答案:

答案 0 :(得分:1)

鉴于

irb(main):001:0> require 'cgi'
=> true

irb(main):002:0> x = "アンジェリーナ・ジョリー"
irb(main):003:0> y = "%E3%82%A2%E3%83%B3%E3%82%B8%E3%82%A7%E3%83%AA%E3%83%BC%E3%83%8A%E3%83%BB%E3%82%B8%E3%83%A7%E3%83%AA%E3%83%BC"
irb(main):005:0> z = "Angelina_Jolie"

要告知字符串已经转义一次,请将字符串与其未转义的值进行比较:

irb(main):141:0> x == CGI::unescape(x)
=> true
irb(main):142:0> y == CGI::unescape(y)
=> false
irb(main):143:0> z == CGI::unescape(z)
=> true

您可以在此处看到y == CGI::unescape(y)返回false。只要您确定字符串中的转义字符是由CGI::escape的应用程序引起的,它应该为您提供所需的答案。我相信这回答了你的第一个问题。

如果字符串可以/应该被转义,那么将在以下比较中返回false

irb(main):017:0> CGI::escape(CGI::unescape(x)) == CGI::unescape(CGI::escape(x))
=> false
irb(main):018:0> CGI::escape(CGI::unescape(y)) == CGI::unescape(CGI::escape(y))
=> true
irb(main):019:0> CGI::escape(CGI::unescape(z)) == CGI::unescape(CGI::escape(z))
=> true

在我的回答中没有上面的第一步,这不允许您区分类型y和类型z,也就是说,您无法告诉y 1}}已被转义且z从未需要它,但至少你知道你不需要再次应用转义。我认为这是你第二个问题的答案。

答案 1 :(得分:1)

确定是否应该通过转义字符串来转义字符串也没有价值。

唯一的情况是,如果没有任何东西可以逃脱,则不会通过转义字符串来更改字符串。在这种情况下,再次逃离的成本可以忽略不计:

CGI.escape(CGI.escape(CGI.escape('foo')))  == 'foo'

如果有东西可以逃脱,通过逃避添加的字符本身就可以逃脱:

CGI.escape('<b>foo</b>')                         == "%3Cb%3Efoo%3C%2Fb%3E" 
CGI.escape(CGI.escape('<b>foo</b>'))             == "%253Cb%253Efoo%253C%252Fb%253E"
CGI.escape(CGI.escape(CGI.escape('<b>foo</b>'))) == '%25253Cb%25253Efoo%25253C%25252Fb%25253E'

再次逃避并不会区分可以转义但尚未转义的内容,而是可以转义且已经转义的内容。

我认为这是确保你只逃避一次的唯一解决办法。

答案 2 :(得分:0)

一种方法是假设如果字符串包含除转义序列以外的可逃避字符,则需要对其进行转义。例如,%3E不需要转义,但%3E>应转义为%253E%3E。您可以通过在转义和重新转义后将字符串与自身进行比较来检查此类字符:

def CGI.maybe_escape str
  return str if str == escape(unescape(str))
  escape str
end

CGI.maybe_escape('>')
# "%3E"
CGI.maybe_escape(CGI.maybe_escape('%3E>'))
# "%253E%3E" <-- only escapes once!