sed паттерн замены ” на \” и \ на \\ за исключением json строки

Вопрос или проблема

У меня проблема с заменой " на \" и \ на \\ и исключением " из json

Входной файл test.txt

"a"     "b"     
{"1":"female","2":"197312","3":"359","4":"201109","5":"mail"}
\uff08\u524d\u5bfe\u5fdc

Я хочу получить вывод в следующем виде

\"a\"     \"b\"     
{"1":"female","2":"197312","3":"359","4":"201109","5":"mail"}
\\uff08\\u524d\\u5bfe\\u5fdc

Чтобы быть более надежным, вы можете выполнить полный разбор json:

perl -0777 -pe '
  s@(".*?"|\\)|(\{(?:"(?:\\.|[^"])*+"|(?2)|[^"{}]++)*+\})|[^{}\\"]+@
  $1 ? $1 =~ s/["\\]/\\$&/gr : $&@gse'

Что на входе, аналогичном

"a"     "b"     "c{d"
{"1":"female","2":"197312","3":"359","4":"201109","5":"mail"}
{
  "1": {"x": "y"}
  "2": "}}}"
  "3": ["{\"x", "}"]
}
\uff08\u524d\u5bfe\u5fdc

дает

\"a\"     \"b\"     \"c{d\"
{"1":"female","2":"197312","3":"359","4":"201109","5":"mail"}
{
  "1": {"x": "y"}
  "2": "}}}"
  "3": ["{\"x", "}"]
}
\\uff08\\u524d\\u5bfe\\u5fdc

Вам может понадобиться уточнить, что вы хотите сделать, если вход содержит "foo\"bar" или "foo\nbar" за пределами json-объектов.

В простом примере, который вы показали, это просто. Просто экранируйте символы только на строках, которые не начинаются с {:

$ sed -E '/^[^{]/s|(["\])|\\\1|g' file 
\"a\"     \"b\"     
{"1":"female","2":"197312","3":"359","4":"201109","5":"mail"}
\\uff08\\u524d\\u5bfe\\u5fdc

Тем не менее, ситуация усложняется, если ваш JSON может занимать несколько строк. Для таких случаев вы можете написать небольшой скрипт, который подсчитывает количество открывающих { и закрывающих }, и применяет замену только тогда, когда эти числа равны (т.е. когда мы не находимся в строке JSON). Что-то вроде:

perl -F'' -ne 'for (@F){$op++ if /{/; $cl++ if /}/; if($cl==$op){s|["\\]|\\$&|g;}print}' file 

Однако это также сломается, если строка JSON сама может содержать { или }, которые не обозначают часть JSON (например, {"1":"b-{c}"} или что-то подобное). Для таких случаев используйте подход Стефана вместо этого.

$ sed 's/\(\\\|^"\|"$\|"[ \t]\)/\\\1/g' test.txt | sed 's/\([ \t]\)"/\1\\"/g'
  • Замените \ или " в начале строки или в конце строки или перед пробелом/символом табуляции:
    's/\(\\\|^"\|"$\|"[ \t]\)/\\\1/g'
  • или " после пробела/символа табуляции: sed 's/\([ \t]\)"/\1\\"/g'

Таким образом, это работает только в том случае, если ваша строка JSON не содержит знаков пробела/символов табуляции и находится в одной строке.

Используя jq:

$ jq -R -rc 'if try fromjson catch false | (type == "object") then . else tojson | ltrimstr("\"") | rtrimstr("\"") end' file
\"a\"     \"b\"
{"1":"female","2":"197312","3":"359","4":"201109","5":"mail"}
\\uff08\\u524d\\u5bfe\\u5fdc

Это считывает каждую строку входных данных из file как сырую текстовую строку и пытается разобрать ее как фрагмент JSON с помощью fromjson. Если это удачно (с использованием try и catch), и если разобранный фрагмент JSON является объектом, то он сохраняется в том виде, в каком был.

Если вход не может быть разобран как JSON, или если это не объект, он кодируется как строка JSON с помощью tojson. Поскольку вход читается как сырой текст, мы дважды кодируем строку, удаляя внешний набор двойных кавычек с помощью ltrimstr() и rtrimstr(), чтобы получить желаемый формат вывода для этих строк, не являющихся объектами JSON.

Ответ или решение

Как заменить символы в текстовом файле с исключением JSON-строк

Введение

В данной статье мы рассмотрим, как с помощью инструментов командной строки, таких как sed и perl, выполнить замену символов в текстовом файле. Основной задачей является замена " на \" и \ на \\, исключая элементы, содержащие JSON. Мы предоставим несколько методов, которые помогут реализовать эту задачу, а также объясним, как правильно обрабатывать строки, содержащие JSON, избегая потенциальных ошибок.

Проблема замены символов

Ваша задача состоит в том, чтобы осуществить замену символов на каждой строке текстового файла, за исключением тех строк, которые содержат JSON. Это может включать создание различных решений в зависимости от сложности JSON и структуры файла.

Простой пример

Предположим, у вас есть файл test.txt со следующим содержимым:

"a"     "b"     
{"1":"female","2":"197312","3":"359","4":"201109","5":"mail"}
\uff08\u524d\u5bfe\u5fdc

Вы хотите преобразовать его в следующий вид:

\"a\"     \"b\"     
{"1":"female","2":"197312","3":"359","4":"201109","5":"mail"}
\\uff08\\u524d\\u5bfe\\u5fdc

Использование sed

Одним из самых простых способов достижения этой цели является использование sed. Однако для обработки JSON нужно учитывать различные особенности форматирования. Вот пример команды:

sed -E '/^[^{]/s|(["\\])|\\\1|g' test.txt

Данная команда заменяет кавычки и обратные слэши на экранированные только в тех строках, которые не начинаются с {, что предполагает отсутствие JSON на этой строке.

Более сложная обработка

Если JSON может занимать несколько строк, следует применить более сложный подход. Например, использование perl для подсчёта открывающих и закрывающих фигурных скобок:

perl -F'' -ne 'for (@F){$op++ if /{/; $cl++ if /}/; if($cl==$op){s|["\\]|\\$&|g;}print}' test.txt

В этом коде мы считываем файл построчно, подсчитываем фигурные скобки и выполняем замену символов только тогда, когда выходим за пределы секции JSON.

Обработка с помощью jq

Для более продвинутого анализа JSON вы можете использовать jq, инструмент, специализированный для работы с JSON:

jq -R -rc 'if try fromjson catch false | (type == "object") then . else tojson | ltrimstr("\"") | rtrimstr("\"") end' test.txt

Эта команда пытается интерпретировать каждую строку как JSON. Если удается, она оставляет строку нетронутой, в противном случае выполняет экранирование.

Заключение

При решении проблемы замены символов в текстовом файле с исключением JSON-строк вам может потребоваться использовать различные подходы в зависимости от сложности данных. Использование sed, perl или jq — это три эффективных способа, которые вы можете комбинировать в зависимости от ваших потребностей. Правильное решение поможет избежать ошибок и улучшить читаемость вашего текста, сохраняя при этом структуру JSON неизменной.

Рекомендации

  1. Тестирование: Всегда тестируйте команды на небольших образцах данных, чтобы убедиться в их корректности.
  2. Резервные копии: Не забудьте создать резервные копии исходных данных.

С помощью приведённых примеров и подходов вы сможете успешно решить задачу замены символов в текстовом файле, исключая при этом элементы JSON.

Оцените материал
Добавить комментарий

Капча загружается...