开发者

Escape status within a string literal as argument of `String#tr`

There is something mysterious to me about the escape status of a backslash within a single quoted string literal as argument of String#tr. Can you explain the contrast between the three examples below? I particularly do not understand the second one. To avoid complication, I am using 'd' here, which does not change the meaning when escaped in double quotation ("\d" = "d").

'\\'.tr('\\', 'x')      #=> "x"
'\\'.tr('\\d', 'x')     #=> "\\开发者_StackOverflow"
'\\'.tr('\\\d', 'x')    #=> "x"


Escaping in tr

The first argument of tr works much like bracket character grouping in regular expressions. You can use ^ in the start of the expression to negate the matching (replace anything that doesn't match) and use e.g. a-f to match a range of characters. Since it has control characters, it also does escaping internally, so you can use - and ^ as literal characters.

print 'abcdef'.tr('b-e', 'x')  # axxxxf
print 'abcdef'.tr('b\-e', 'x') # axcdxf

Escaping in Ruby single quote strings

Furthermore, when using single quotes, Ruby tries to include the backslash when possible, i.e. when it's not used to actually escape another backslash or a single quote.

# Single quotes
print '\\'    # \
print '\d'    # \d
print '\\d'   # \d
print '\\\d'  # \\d

# Double quotes
print "\\"    # \
print "\d"    # d
print "\\d"   # \d
print "\\\d"  # \d

The examples revisited

With all that in mind, let's look at the examples again.

'\\'.tr('\\', 'x')      #=> "x"

The string defined as '\\' becomes the literal string \ because the first backslash escapes the second. No surprises there.

'\\'.tr('\\d', 'x')     #=> "\\"

The string defined as '\\d' becomes the literal string \d. The tr engine, in turn uses the backslash in the literal string to escape the d. Result: tr replaces instances of d with x.

'\\'.tr('\\\d', 'x')    #=> "x"

The string defined as '\\\d' becomes the literal \\d. First \\ becomes \. Then \d becomes \d, i.e. the backslash is preserved. (This particular behavior is different from double strings, where the backslash would be eaten alive, leaving only a lonesome d)

The literal string \\d then makes tr replace all characters that are either a backslash or a d with the replacement string.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜