Вопрос или проблема
У меня есть строка, указанная ниже. Мне просто нужно получить первую accountHeader (жирным) строку JSON.
<START AdditionalInfo#:>[FormsGenerationServiceImpl::, accountNumber:ABC07667 , [Source System Request : {"Info":{"Holder": {"nameData": {"shortName": "McIntosh"}},**"accountHeader": {"a": "Y","b": "1","c": "4","draft": "P","e": "Y0000DU9","f": "T","g": "1"}**,"forms": {"maskSSN": "N","deliverForms": "G","selectedForms": {"T5": ["F10"],"T1": ["F1403"],"T2": ["F100001401"]}},"accountHeader": {"a": "Y","b": "1","c": "4","d": "HWA","draftRequestType": "P","e": "Y0000DU9","f": "T","g": "1"}}} ], null]<AdditionalInfo#: END>
Мой вывод должен быть
"accountHeader": {"a": "Y","b": "1","c": "4","draft": "P","e": "Y0000DU9","f": "T","g": "1"}
Вот несколько вариантов:
-
Используйте
grep
с флагом-o
, чтобы вывести только совпадающую часть строки, и отфильтруйте с помощьюhead
, чтобы получить только первое совпадение:grep -o '"accountHeader[^}]*}' file.json | head -n1
Регулярное выражение ищет
"accountHeader
, а затем столько, сколько возможно, не-}
символов до первого}
. Это в основном то же самое регулярное выражение, что используется и в других решениях ниже. -
Используйте
sed
с-n
, чтобы подавить печать, иp
после замены, чтобы печатать только в случае успешной замены. Затем замените (удалите) все, кроме того, что вам нужно:sed -n 's/.*\("accountHeader[^}]*}\).*/\1/p' file.json
-
Используйте Perl,
-l
добавляет новую строку к каждому вызовуprint
,-n
означает “обработать каждую строку входного файла” и применить скрипт, данный-e
:perl -lne '/.*("accountHeader[^}]*})/ && print $1' file.json
-
Используйте
awk
, предполагая, что**
в вашем примере ввода присутствуют для выделения интересующей вас части и фактически не существуют в реальных данных. Если так, это должно сработать:awk -F'},' '{print $2"}"}' file.json
Если **
действительно присутствуют, все еще проще, просто используйте их в качестве разделителей полей:
awk -F'**' '{print $2"}"}' file.json
или
perl -F"\*\*" -alne 'print $F[1]' file.json
Этот ответ предполагает, что **
в данных были добавлены в попытке вставить жирный текст в вопрос (т.е. что это на самом деле не часть данных).
$ sed -e 's/[^{]*{/{/' -e 's/}[^}]*$/}/' file | jq '.Info.accountHeader'
{
"a": "Y",
"b": "1",
"c": "4",
"d": "HWA",
"draftRequestType": "P",
"e": "Y0000DU9",
"f": "T",
"g": "1"
}
Команда sed
извлекает встроенный документ JSON из оберточного документа, обрезая все, что перед первой {
, и после последней }
.
Команда jq
извлекает объект accountHeader
, часть верхнего уровня объекта Info
.
Если вы хотите вывод в одной строке, попросите jq
дать вам “компактный” вывод, добавив опцию -c
:
$ sed -e 's/[^{]*{/{/' -e 's/}[^}]*$/}/' file | jq -c '.Info.accountHeader'
{"a":"Y","b":"1","c":"4","d":"HWA","draftRequestType":"P","e":"Y0000DU9","f":"T","g":"1"}
Если вы хотите сохранить ключ accountHeader
, то извлеките объект Info
и используйте pick()
, чтобы выбрать ключ:
$ sed -e 's/[^{]*{/{/' -e 's/}[^}]*$/}/' file | jq -c '.Info | pick(.accountHeader)'
{"accountHeader":{"a":"Y","b":"1","c":"4","d":"HWA","draftRequestType":"P","e":"Y0000DU9","f":"T","g":"1"}}
В старых версиях jq
эта функция pick()
может быть недоступна; вам придется пойти долгим путем и выбрать ключ вручную:
$ sed -e 's/[^{]*{/{/' -e 's/}[^}]*$/}/' file | jq -c '.Info | with_entries(select(.key == "accountHeader"))'
{"accountHeader":{"a":"Y","b":"1","c":"4","d":"HWA","draftRequestType":"P","e":"Y0000DU9","f":"T","g":"1"}}
Ответ или решение
Как извлечь JSON-строку из данной строки
Если вам необходимо извлечь первую строку JSON с ключом accountHeader
из предоставленной строки, вы можете использовать несколько эффективных подходов. Давайте рассмотрим пошагово различные методы, которые помогут вам достичь этой цели, разбирая каждый из них отдельно.
1. Использование grep
Команда grep
является одним из самых простых способов извлечения текстовой информации из файла. В вашем случае можно использовать следующую команду:
grep -o '"accountHeader[^}]*}' файл.json | head -n1
Объяснение:
- -o: выводит только найденные совпадения.
- *"accountHeader[^}]}**: регулярное выражение находит строку, начинающуюся с
"accountHeader
, за которой следуют любые символы, кроме}
). Это позволит захватить всю информацию до первой закрывающей фигурной скобки.
2. Использование sed
Когда вам необходимо тоньше контролировать извлечение, команду sed
можно использовать следующим образом:
sed -n 's/.*\("accountHeader[^}]*}\).*/\1/p' файл.json
Объяснение:
- -n: подавляет автоматический вывод.
- s/PATTERN/REPLACEMENT/: заменяет всё, что не соответствует
accountHeader
, оставляя только искомую часть.
3. Использование perl
Если вам нужно более мощное решение, обратите внимание на perl
:
perl -lne '/.*("accountHeader[^}]*})/ && print $1' файл.json
Объяснение:
- -l: добавляет новую строку к каждому вызову
print
. - -n: обрабатывает каждую строку файла.
4. Использование awk
Если структура вашего JSON стабильна, awk
может быть полезным:
awk -F'},' '{print $2"}"}' файл.json
Объяснение:
- -F’},’: установите разделитель полей, при этом второе поле будет содержать нужный фрагмент JSON.
5. Изменение формата данных
Если в вашей строке присутствуют символы **
, эти символы можно использовать как разделители:
awk -F'**' '{print $2"}"}' файл.json
или
perl -F"\*\*" -alne 'print $F[1]' файл.json
6. Использование jq
Если вы используете jq
для обработки JSON, вот как это можно сделать:
sed -e 's/[^{]*{/{/' -e 's/}[^}]*$/}/' файл | jq -c '.Info.accountHeader'
Объяснение:
sed
извлекает JSON, обеспечивая, что мы работаем только с открывающей{
и закрывающей}
фигурными скобками.jq
затем извлекает объектaccountHeader
из объектаInfo
.
Заключение
Каждый из представленных методов имеет свои особенности и может быть применим в различных сценариях в зависимости от ваших нужд. Выбор подхода зависит от ваших инструментов и от формата данных, заменяя сложность более простыми решениями, если это возможно. Таким образом, используя описанные техники, вы сможете легко извлечь необходимую часть JSON из строки, что сэкономит ваше время и усилия для дальнейшей работы с данными.