[英]Ruby's string: Escape and unescape a custom character
假设我说£
字符是危险的,我希望能够保护和取消保护任何字符串。 反之亦然。
例1:
"Foobar £ foobar foobar foobar." # => dangerous string
"Foobar \£ foobar foobar foobar." # => protected string
例2:
"Foobar £ foobar £££££££foobar foobar." # => dangerous string
"Foobar \£ foobar \£\£\£\£\£\£\£foobar foobar." # => protected string
例3:
"Foobar \£ foobar \\£££££££foobar foobar." # => dangerous string
"Foobar \£ foobar \\\£\£\£\£\£\£\£foobar foobar." # => protected string
有一个简单的方法,使用Ruby,从字符串中逃避(和unescape)给定字符(例如我的例子中的£
)?
编辑:这里是关于这个问题的行为的解释。
首先,感谢您的回答。 我有一个带有Tweet
模型的Rails应用程序,它有一个content
字段。 推文示例:
tweet = Tweet.create(content: "Hello @bob")
在模型内部,有一个序列化过程可以转换字符串,如下所示:
dump('Hello @bob') # => '["Hello £", 42]'
# ... where 42 is the id of bob username
然后,我能够反序列化并显示它的推文:
load('["Hello £", 42]') # => 'Hello @bob'
同样,使用多个用户名也可以这样做:
dump('Hello @bob and @joe!') # => '["Hello £ and £!", 42, 185]'
load('["Hello £ and £!", 42, 185]') # => 'Hello @bob and @joe!'
这就是目标:)
但是,这种查找和替换可能很难通过以下方式执行:
tweet = Tweet.create(content: "£ Hello @bob")
因为在这里我们也必须逃避£
char。 我认为你的解决方案对此有好处。 结果变成了:
dump('£ Hello @bob') # => '["\£ Hello £", 42]'
load('["\£ Hello £", 42]') # => '£ Hello @bob'
刚刚好。 <3 <3
现在,如果有这样的话:
tweet = Tweet.create(content: "\£ Hello @bob")
我认为我们首先应该对每个\\
进行转义,然后对每个£
进行转义,例如:
dump('\£ Hello @bob') # => '["\\£ Hello £", 42]'
load('["\\£ Hello £", 42]') # => '£ Hello @bob'
但是......在这种情况下我们该怎么做:
tweet = Tweet.create(content: "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\£ Hello @bob")
...其中tweet.content.gsub(/(?<!\\\\)(?=(?:\\\\\\\\)*£)/, "\\\\")
似乎不起作用。
希望您的Ruby版本支持lookbehinds。 如果没有,我的解决方案将无法为您服务。
转义字符:
str = str.gsub(/(?<!\\)(?=(?:\\\\)*£)/, "\\")
取消转义字符:
str = str.gsub(/(?<!\\)((?:\\\\)*)\\£/, "\1£")
不管反斜杠的数量如何,这两个正则表达式都可以工作。 它们是相辅相成的。
转义说明:
"
(?<! # Assert that it is impossible to match the regex below with the match ending at this position (negative lookbehind)
\\ # Match the character “\” literally
)
(?= # Assert that the regex below can be matched, starting at this position (positive lookahead)
(?: # Match the regular expression below
\\ # Match the character “\” literally
\\ # Match the character “\” literally
)* # Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
£ # Match the character “£” literally
)
"
不是说我匹配某个位置。 根本不消耗任何文本。 当我确定位置时,我要插入\\。
unescape的说明:
"
(?<! # Assert that it is impossible to match the regex below with the match ending at this position (negative lookbehind)
\\ # Match the character “\” literally
)
( # Match the regular expression below and capture its match into backreference number 1
(?: # Match the regular expression below
\\ # Match the character “\” literally
\\ # Match the character “\” literally
)* # Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
)
\\ # Match the character “\” literally
£ # Match the character “£” literally
"
在这里,我保存所有的反斜杠减一,然后用特殊字符替换此反斜杠的数量。 棘手的东西:)
如果你使用的是Ruby 1.9,它有后观,那么FailedDev的答案应该可以很好地运行。 如果您使用的是Ruby 1.8(我认为该方法没有落后之处),则可以使用其他方法。 尝试一下:
text.gsub!(/(\\.)|£)/m) do
if ($1 != nil) # If escaped anything
"$1" # replace with self.
else # Otherwise escape the
"\\£" # unescaped £.
end
end
请注意,我不是Ruby程序员,这个代码段未经测试(特别是我不确定: if ($1 != nil)
语句用法是否正确-它可能需要是: if ($1 != "")
或if ($1)
),但我确实知道这种通用技术(使用代码代替简单的替换字符串)有效。 我最近在JavaScript解决方案中使用了相同的技术来解决类似的问题 ,该问题旨在查找未转义的星号。
我不确定这是不是你想要的,但我认为你可以做一个简单的查找和替换:
str = str.gsub("£", "\\£") # to escape
str = str.gsub("\\£", "£") # to unescape
请注意,我将\\
更改为\\\\
因为您必须在双引号字符串中转义反斜杠。
编辑:我认为你想要的是一个匹配奇数反斜杠的正则表达式:
str = str.gsub(/(^|[^\\])((?:\\\\)*)\\£/, "\\1\\2£")
这做了以下转换
"£" #=> "£"
"\\£" #=> "£"
"\\\\£" #=> "\\\\£"
"\\\\\\£" #=> "\\\\£"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.