我正在尝试使用自己的JSON解析器。我有一个我想要标记的输入字符串:
input = "{ \"foo\": \"bar\", \"num\": 3}"
如何删除转义字符\
,使其不属于我的令牌?
目前,我使用delete
的解决方案有效:
tokens = input.delete('\\"').split("")
=> ["{", " ", "f", "o", "o", ":", " ", "b", "a", "r", ",", " ", "n", "u", "m", ":", " ", "3", "}"]
但是,当我尝试使用gsub
时,它无法找到任何\"
。
tokens = input.gsub('\\"', '').split("")
=> ["{", " ", "\"", "f", "o", "o", "\"", ":", " ", "\"", "b", "a", "r", "\"", ",", " ", "\"", "n", "u", "m", "\"", ":", " ", "3", "}"]
我有两个问题:
1。为什么gsub在这种情况下不起作用?
2。如何删除反斜杠(转义)字符?我目前必须使用引号删除反斜杠字符才能使其正常工作。
答案 0 :(得分:26)
当你写:
input = "{ \"foo\": \"bar\", \"num\": 3}"
存储在输入中的实际字符串是:
{ "foo": "bar", "num": 3}
这里的转义\"
由Ruby解析器解释,因此它可以区分字符串的边界(最左边和最右边"
)和普通字符{{1在一个字符串(转义的)中。
"
删除字符集指定的第一个参数,而不是模式。将删除第一个参数中的所有字符。所以通过写作
String#delete
您从input.delete('\\"')
中删除了所有\
和"
的字符串,而不是从input
删除了所有\"
序列的字符串。这对你的情况是错误的。一段时间后它可能会导致意外行为。
input
替换模式(正则表达式或纯字符串)。
String#gsub
表示查找所有input.gsub('\\"', '')
(序列中的两个字符)并将其替换为空字符串。由于\"
中没有\
,因此没有任何内容被替换。你需要的是:
input
答案 1 :(得分:8)
你不在你的字符串中有反斜杠。您的字符串中有引号,当放在双引号字符串中时需要对其进行转义。看:
input = "{ \"foo\": \"bar\", \"num\": 3}"
puts input
# => { "foo": "bar", "num": 3}
你正在删除 - 幽灵。
input.delete('\\"')
将删除其参数中的任何字符。因此,您删除任何不存在的反斜杠,并删除所有引号。如果没有引号,默认显示方法(inspect
)将不需要转义任何内容。
input.gsub('\\"', '')
会尝试删除不存在的序列\"
,因此gsub
最终无效。
确保您知道字符串表示(puts input.inspect
)和字符串内容(puts input
)之间的区别,并注意反斜杠作为表示的工件。
那就是说,我必须回应emaillenin:编写一个正确的JSON解析器并不简单,你不能用正则表达式来做(或者至少不能用常规正则表达式;它可能有Oniguruma)。它需要一个适当的解析器,如treetop或rex / racc,因为它有很多很容易错过的极端情况(其中主要是讽刺性的,转义字符)。
答案 2 :(得分:1)
使用正则表达式:
> input = "{ \"foo\": \"bar\", \"num\": 3}"
> input.gsub(/"/,'').split("")
> => ["{", " ", "f", "o", "o", ":", " ", "b", "a", "r", ",", " ", "n", "u", "m", ":", " ", "3", "}"]
这实际上只是一个双引号。斜线是逃避它。
答案 3 :(得分:1)
input.gsub(/[\"]/,"")
也可以。