Удаление обратной косой черты (escape-символ) из строки
Я пытаюсь работать над своим парсером JSON. У меня есть строка ввода, которую я хочу tokenize:
input = "{ \"foo\": \"bar\", \"num\": 3}"
Как удалить escape-символ \
, чтобы он не был частью моих токенов?
В настоящее время мое решение с использованием 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. Как удалить символ обратной косой черты (escape)? В настоящее время я должен удалить символ обратной косой черты с помощью кавычек, чтобы сделать эту работу.
Ответы
Ответ 1
Когда вы пишете:
input = "{ \"foo\": \"bar\", \"num\": 3}"
Фактическая строка, хранящаяся на входе:
{ "foo": "bar", "num": 3}
Вывод \"
здесь интерпретируется синтаксическим анализатором Ruby, так что он может различать границу строки (наиболее левую и правую большую "
) и нормальный символ "
в строке ( беглые).
String#delete
удаляет набор символов, указанный первым параметром, а не шаблоном. Все символы, которые находятся в первом параметре, будут удалены. Итак, написав
input.delete('\\"')
У вас есть строка со всеми \
и "
удалена из input
, а не строка со всей последовательностью \"
, удаленной из input
. Это неверно для вашего дела. Это может вызвать неожиданное поведение спустя некоторое время.
String#gsub
, однако, замените шаблон (либо регулярное выражение, либо обычную строку).
input.gsub('\\"', '')
означает найти все \"
(два символа в последовательности) и заменить их пустой строкой. Поскольку в input
нет \
, ничего не заменилось. На самом деле вам нужно:
input.gsub('"', '')
Ответ 2
У вас нет обратной косой черты в вашей строке. У вас есть кавычки в вашей строке, которые должны быть экранированы при размещении в строке с двумя кавычками. Посмотрите:
input = "{ \"foo\": \"bar\", \"num\": 3}"
puts input
# => { "foo": "bar", "num": 3}
Вы удаляете - фантомы.
input.delete('\\"')
удалит любые символы в своем аргументе. Таким образом, вы удаляете любые несуществующие обратные слэши, а также удаляете все кавычки. Без кавычек метод отображения по умолчанию (inspect
) не нуждается ни в чем.
input.gsub('\\"', '')
попытается удалить последовательность \"
, которая не существует, поэтому gsub
ничего не делает.
Убедитесь, что вы знаете, какая разница между строковым представлением (puts input.inspect
) и содержимым строки (puts input
), и обратите внимание на обратную косую черту как на артефакты представления.
Тем не менее, я должен повторить эмаиленин: писать правильный парсер JSON непросто, и вы не можете делать это с помощью регулярных выражений (или, по крайней мере, не с регулярными регулярными выражениями, возможно, с Oniguruma). Он нуждается в правильном парсере, таком как treetop или rex/racc, поскольку у него много угловых случаев, которые легко пропустить (главными из них являются, по иронии судьбы, экранированные персонажи).
Ответ 3
Использовать шаблон регулярного выражения:
> input = "{ \"foo\": \"bar\", \"num\": 3}"
> input.gsub(/"/,'').split("")
> => ["{", " ", "f", "o", "o", ":", " ", "b", "a", "r", ",", " ", "n", "u", "m", ":", " ", "3", "}"]
Это фактически двойная кавычка. Слэш должен убежать от него.
Ответ 4
input.gsub(/[\"]/,"")
также будет работать.