
У меня есть test.json
файл с разной длиной строк. Какой-то вымышленный пример:
{ a: 123, b: sd, c: x45, d: 1, e: '' }
{ a: 5, b: bfgg, c: x4c, d: 31, e: '' }
Я хочу вырезать всю подстроку после d
-части и получить обратно только для каждой строки:
{ a: 123, b: sd, c: x45 }
{ a: 5, b: bfgg, c: x4c }
я нашелздесьаналогичный вопрос и попытался адаптировать свою проблему к нему:
echo test.json | sed 's/. d:/' > newtest.json
Мне нужно сделать это для всего файла, а не только для одной строки.
решение1
Если вы часто работаете с преобразованием JSON в командной строке, вам стоит потратить время на приобретение инструмента JQ и научиться им пользоваться.
Хотя приведенные выше ответы показывают, что вы можете выполнять минимальные преобразования без фактического анализа JSON, в конечном итоге вам придется либо заново изобрести глючный парсер JSON с помощью регулярных выражений, либо вернуться к использованию собственного парсера JSON на выбранном вами языке.
jq — быстрый, простой в использовании и очень удобный инструмент, который стоит иметь в своем арсенале.
BWT, ваши тестовые данные — недействительный json, что усложнит решения выше. Если вы исправите это на
{ "a":123 , "b": "sd", "c": "x45", "d": 1, "e": "" }
{ "a":5 , "b": "bfgg", "c": "x4c", "d": 31, "e": "" }
Тогда эта команда jq сделает то, что вы хотите
jq -c '{a,b,c}' test.json
{"a":123,"b":"sd","c":"x45"}
{"a":5,"b":"bfgg","c":"x4c"}
решение2
sed '/d:/s/, d:[^}]*/ /' test.json
он пройдет по всему файлу и удалит в каждой строке d:
всю , d:.*
часть до }
символа ( }
символ останется на строке).
решение3
Ответ @Rush, sed
вероятно, является лучшим способом решения этой проблемы, но вот как вы можете сделать это awk
также, используя:
$ awk -F ', d.* ' '{print $1, $2}' file.txt
{ a: 123, b: sd, c: x45 }
{ a: 5, b: bfgg, c: x4c }
Вышеприведенное используется awk
для разделения данных на , d.*
. Это создает 2 поля данных, $1
которые $2
содержат данные, полученные в результате разделения строк AWK.
решение4
Предположим, у вас есть действительный файл JSON, содержащий набор объектов, например
{"a":123,"b":"sd","c":"x45","d":1,"e":"''"}
{"a":5,"b":"bfgg","c":"x4c","d":31,"e":"''"}
или эквивалент
{
"a": 123,
"b": "sd",
"c": "x45",
"d": 1,
"e": "''"
}
{
"a": 5,
"b": "bfgg",
"c": "x4c",
"d": 31,
"e": "''"
}
и вы хотели бы удалить ключи d
и e
из каждого объекта.
Используя jq
, удаляем по одному ключу за раз:
jq -c 'del(.d) | del(.e)' file.json
Удаление обоих ключей одновременно:
jq -c 'del(.d, .e)' file.json
Результатом любого из этих действий будет
{"a":123,"b":"sd","c":"x45"}
{"a":5,"b":"bfgg","c":"x4c"}
Третий способ сделать это, не упоминающий фактические ключи по имени, — преобразовать объекты в списки «записей» с помощью to_entries
, затем удалить последние две записи и преобразовать список обратно в измененный объект:
jq -c 'to_entries | del(.[-2:]) | from_entries' file.json
Это больше всего похоже на то, что предлагается в тексте вопроса, а результат зависит от порядка ключей в объекте.