Вложенные структуры данных (, такие как JSON ), должны анализироваться соответствующими инструментами (, например. json -известно здесь ), чтобы правильно извлечь информацию. Попытка работать с вложенными структурами данных только с помощью подпрограмм, поддерживающих строку -(, таких как grep/sed/awk/etc ), приведет к сбоям и ложным срабатываниям. Например, приведенный выше ответ будет работать только в том случае, если ваш JSON будет красиво -напечатан с каждым элементом JSON по одному в строке. Хотя это потерпит неудачу, если JSON будет напечатан как-то иначе (, то есть в одной строке, или с несколькими элементами в одной строке ).
Таким образом, если вы используете python, вам нужно разобрать объект, а затем извлечь необходимые данные программно (, т.е. написать скрипт на python ).
Тем не менее, есть еще один подход :для unix, есть несколько утилит, поддерживающих число или json -, разработанных для довольно легкого выполнения запроса, подобного вашему, например. jq, jtc (и многие другие ). Здесь позвольте мне показать вам решение, основанное наjtc:
Предполагая, что у вас есть следующий json:
bash $ cat file.json
{
"Root": [
{
"data": "2.71",
"test": "e"
},
{
"data": "3.14",
"test": "pi"
}
]
}
bash $
затем, чтобы извлечь все объекты, содержащие "test": "pi"
, использование jtc
выглядит следующим образом:
bash $ cat file.json | jtc -w'[test]:: [-1]'
{
"data": "3.14",
"test": "pi"
}
bash $
пояснение к обходу -путь(-w
)параметры:
1. [test]:
найдет все элементы типа "test": "pi"
(, если их несколько)
2. [-1]
повысит уровень JSON на 1 по сравнению с найденным элементом (s ).
результирующие прогулки (с )будут напечатаны.
См. jtc
полное руководство пользователя здесь:https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md
Такие инструменты, как grep
, сопоставляют только одну строку за раз, поэтому при использовании grep
вы не можете сопоставить все это с помощью одного регулярного выражения.
Вы можете использовать такой инструмент, как sed
, чтобы извлечь только часть вложенного блока, а затем передать ее в grep
для поиска интересующего вас сообщения об ошибке.
Команда /START/,/END/p
в sed
будет печатать только строки между блоком, начинающимся и заканчивающимся строками, соответствующими двум регулярным выражениям. Кроме того, вы должны передать sed
аргумент -n
, чтобы он не печатал никаких строк по умолчанию.
Так:
$ sed -n '/^##$/,/^##$/p' mylogfile.txt |
grep -iq '^some_error_message$'
Perl легко решает эту проблему с помощью своего оператора range , иногда называемого оператором flip-flop
:
perl -nle 'if (/^##/.../^##/) {print if /some_error_message/i}' file
Это читает ваш файл, ища блок, который начинается и заканчивается с помощью ##
, привязанного к началу строки. Затем внутри блока печатается любая строка с токеном some_error_message
. В этом примере «некоторое _сообщение об ошибке _» сопоставляется без учета регистра.
Простая версия, простоsed
(обычно вам не нужно направлять sed
вывод по конвейеру, просто объединяйте команды с;
):
sed '/^##$/,//!d;/some_error_message/!d'
Во-первых, мы создаем диапазон адресов от^##$
(строки всего##
)до пустого шаблона (, что означает :повторение последнего шаблона, таким образом, снова ##
строка ). Инвертируйте совпадение с !
и d
, чтобы удалить все, что находится за пределами диапазона.
Во-вторых, d
удалить все строки, не(!
)содержащие some_error_message
.