如何从ruby中取消显示c风格的转义序列?
在ruby中,如何解码c风格的转义序列?e、 g.“\n”到换行符,“\t”到制表符?更短,更黑,更危险,因为评估:如何从ruby中取消显示c风格的转义序列?,ruby,Ruby,在ruby中,如何解码c风格的转义序列?e、 g.“\n”到换行符,“\t”到制表符?更短,更黑,更危险,因为评估: eval“\”{string}\” 一个简单的例子: >a='1\t2\n3' >提出 1\t2\n3 >将求值“\”{a}”放入 1 2 3. 编辑:请注意,这实际上不起作用。您确实需要在这里使用状态机构建一个适当的解析器,该状态机跟踪您是否处于转义序列中 Ruby支持许多相同的转义序列,因此您可以构建一个简单的转换表,如下所示: T = { '\n' =&
eval“\”{string}\”
一个简单的例子:
>a='1\t2\n3'
>提出
1\t2\n3
>将求值“\”{a}”放入
1 2
3.
编辑:请注意,这实际上不起作用。您确实需要在这里使用状态机构建一个适当的解析器,该状态机跟踪您是否处于转义序列中
Ruby支持许多相同的转义序列,因此您可以构建一个简单的转换表,如下所示:
T = {
'\n' => "\n",
'\t' => "\t",
'\r' => "\r"
}
然后使用该转换表替换源字符串中的序列:
a = '1\t2\n3'
a.gsub(/#{T.keys.map(&Regexp.method(:escape)).join('|')}/, &T.method(:[]))
# => "1\t2\n3"
好的,如果您不喜欢
eval
解决方案,我已经在Ruby中入侵了一个简单的状态机来正确解析字符串中的简单“\n”和“\t”,包括反斜杠本身的预转义。这是:
BACKSLASH = "\\"
def unescape_c_string(s)
state = 0
res = ''
s.each_char { |c|
case state
when 0
case c
when BACKSLASH then state = 1
else res << c
end
when 1
case c
when 'n' then res << "\n"; state = 0
when 't' then res << "\t"; state = 0
when BACKSLASH then res << BACKSLASH; state = 0
else res << BACKSLASH; res << c; state = 0
end
end
}
return res
end
以下代码将正确解码ISO-C标准定义的所有转义序列。这是节省和合理的性能:
ISO_C_ESCAPE_SEQUENCES = %r{
# One letter escapes
(?:\\[abfnrtv\\'"?])
# Hex encoded character
| (?:\\(x)([A-Fa-f0-9]{2,}))
# Any Unicode code point (8 hex digits) or
# Unicode code point below 1000 (4 hex digits)
| (?:\\(u)((?:[A-Fa-f0-9]{8})|(?:[A-Fa-f0-9]{4})))
# Octal encoded character
| (?:\\([0-7]{1,3}))
}x
ISO_C_ONE_LETTER_ESCAPES = {
"\\a" => "\a",
"\\b" => "\b",
"\\f" => "\f",
"\\n" => "\n",
"\\r" => "\r",
"\\t" => "\t",
"\\v" => "\v",
"\\\\" => "\\",
"\\'" => "'",
"\\\"" => "\"",
"\\?" => "?"
}
def decodeCString( cString )
return cString.gsub(ISO_C_ESCAPE_SEQUENCES) { |match|
replacement = ISO_C_ONE_LETTER_ESCAPES[match]
next replacement if replacement
next $2.to_i(16).chr if $1 == "x"
next $4.to_i(16).chr(Encoding::UTF_8) if $3 == "u"
next $5.to_i(8).chr
}
end
以下是一个示例:
puts decodeCString("Line \\\\n Same Line!\\nNew line\\x0ANew line")
puts decodeCString("Smiley: \\u263A\tHorse head: \\u00010083")
puts decodeCString("Equal sign in quotes: \\\"\\75\\\"")
印刷品
Line\n同一行!
新线
新线
斯迈利:☺ 马头:也不行;解析“\n”结构比搜索和替换要困难一些-您必须首先注意转义序列的转义。事实上,一行一个字节地去做要容易得多。不过我喜欢你用T
做的事情!
require 'test/unit'
class TestEscapeCString < Test::Unit::TestCase
def test_1
assert_equal("abc\nasd", unescape_c_string('abc\nasd'))
end
def test_2
assert_equal("abc\tasd", unescape_c_string('abc\tasd'))
end
def test_3
assert_equal("abc\\asd", unescape_c_string('abc' + BACKSLASH * 2 + 'asd'))
end
def test_4
assert_equal("abc\\nasd", unescape_c_string('abc' + BACKSLASH * 2 + 'nasd'))
end
def test_5
assert_equal("abc\\\nasd", unescape_c_string('abc' + BACKSLASH * 3 + 'nasd'))
end
def test_6
assert_equal("abc\\\\nasd", unescape_c_string('abc' + BACKSLASH * 4 + 'nasd'))
end
end
ISO_C_ESCAPE_SEQUENCES = %r{
# One letter escapes
(?:\\[abfnrtv\\'"?])
# Hex encoded character
| (?:\\(x)([A-Fa-f0-9]{2,}))
# Any Unicode code point (8 hex digits) or
# Unicode code point below 1000 (4 hex digits)
| (?:\\(u)((?:[A-Fa-f0-9]{8})|(?:[A-Fa-f0-9]{4})))
# Octal encoded character
| (?:\\([0-7]{1,3}))
}x
ISO_C_ONE_LETTER_ESCAPES = {
"\\a" => "\a",
"\\b" => "\b",
"\\f" => "\f",
"\\n" => "\n",
"\\r" => "\r",
"\\t" => "\t",
"\\v" => "\v",
"\\\\" => "\\",
"\\'" => "'",
"\\\"" => "\"",
"\\?" => "?"
}
def decodeCString( cString )
return cString.gsub(ISO_C_ESCAPE_SEQUENCES) { |match|
replacement = ISO_C_ONE_LETTER_ESCAPES[match]
next replacement if replacement
next $2.to_i(16).chr if $1 == "x"
next $4.to_i(16).chr(Encoding::UTF_8) if $3 == "u"
next $5.to_i(8).chr
}
end
puts decodeCString("Line \\\\n Same Line!\\nNew line\\x0ANew line")
puts decodeCString("Smiley: \\u263A\tHorse head: \\u00010083")
puts decodeCString("Equal sign in quotes: \\\"\\75\\\"")