开发者

Ruby Regexp: How do I replace doubly escaped characters such as \\n with \n

So, I have开发者_开发技巧

puts "test\\nstring".gsub(/\\n/, "\n")

and that works.

But how do I write one statement that replaces \n, \r, and \t with their correctly escaped counterparts?


You have to use backreferences. Try

puts "test\\nstring".gsub(/(\\[nrt])/, $1)

gsub sets $n (where 'n' is the number of the corresponding group in the regular expression used) to the content matched the pattern.

EDIT: I modified the regexp, now the output should be:

test\nstring

The \n won't be intepreted as newline by puts.


Those aren't escaped characters, those are literal characters that are only represented as being escaped so they're human readable. What you need to do is this:

escapes = {
  'n' => "\n",
  'r' => "\r",
  't' => "\t"
}

"test\\nstring".gsub(/\\([nrt])/) { escapes[$1] }
# => "test\nstring"

You will have to add other escape characters as required, and this still won't accommodate some of the more obscure ones if you really need to interpret them all. A potentially dangerous but really simple solution is to just eval it:

eval("test\\nstring")

So long as you can be assured that your input stream doesn't contain things like #{ ... } that would allow injecting arbitrary Ruby, which is possible if this is a one shot repair to fix some damaged encoding, this would be fine.

Update

There might be a mis-understanding as to what these backslashes are. Here's an example:

"\n".bytes.to_a
# => [10]

"\\n".bytes.to_a
# => [92, 110]

You can see these are two entirely different things. \n is a representation of ASCII character 10, a linefeed.


through the help of @tadman, and @black, I've discovered the solution:

>> escapes = {'\\n' => "\n", '\\t' => "\t"}
=> {"\\t"=>"\t", "\\n"=>"\n"}
>> "test\\nstri\\tng".gsub(/\\([nrt])/) { |s| escapes[s] }
=> "test\nstri\tng"
>> puts "test\\nstri\\tng".gsub(/\\([nrt])/) { |s| escapes[s] }
test
stri    ng
=> nil

as it turns out, ya just map the \\ to \ and all is good. Also, you need to use puts for the terminal to output the whitespace correctly.

 escapes = {'\\n' => "\n", '\\t' => "\t"}
puts "test\\nstri\\tng".gsub(/\\([nrt])/) { |s| escapes[s] }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜