簡體   English   中英

Ruby的字符串:Escape和unescape自定義字符

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM