По сути, это вопрос захвата тех частей, которые вам нужны, и отбрасывания тех, которые вам не нужны. Например, используя sed
, вы можете захватить целочисленное значение Success
и скопировать его в область хранения(h ), извлекая и добавляя его(G)к захваченным цифрам Completed
. ] строка:
sed -nE \
-e '/Success/ {s/.* ([0-9]+).*/\1/; h;}' \
-e '/Completed/{G; s/.*T_init = ([0-9]+)\.00 degC & T_sink = ([0-9]+).*\n/\1 \2 /; p;}
' terminal_output.txt
Perl предоставляет несколько более выразительный синтаксис, который, ИМХО, более удобочитаем.:
perl -lne '
our $a = $1 if /Success.*?(\d+)/; print join " ", /(\d+)\.\d+/g, $a if /Completed/
' terminal_output.txt
дает желаемый результат
25 35 128
30 40 307
Это может быть полезно.
grep -B 6 AVAILABLE db_systems.txt | grep db-unique-name
Попробуйте это,
Использованиеgrep
:
grep -B6 AVAILABLE file | grep db-unique-name
"db-unique-name": "p00z5bj_iad2bj",
B
Печатать NUM строк начального контекста перед сопоставлением строк. Использованиеawk
:
awk '{a[++i]=$0;}/AVAILABLE/{print a[NR-6];}' file
"db-unique-name": "p00z5bj_iad2bj",
Вы можете попробовать это с GNUawk
:
awk -F',' 'BEGIN { RS = "--" } /"lifecycle-state": "AVAILABLE"/ { gsub("^[[:blank:]]*", "", $1); print $1 }' file
Выход:
"db-unique-name":"p00z5bj_iad2bj"
Это должно работать:
$ awk '$1=="\"db-unique-name\":"{name=$2}
$1=="\"lifecycle-state\":" && $2 ~ /AVAILABLE/ {print name}' systems.txt
"p00z5bj_iad2bj",
Или, если вам нужна вся строка db-unique-name
, попробуйте:
$ awk '$1=="\"db-unique-name\":"{name=$0}
$1=="\"lifecycle-state\":" && $2 ~ /AVAILABLE/ {print name}' systems.txt
"db-unique-name": "p00z5bj_iad2bj",
Если вы имеете дело с данными в формате JSON, (фрагменты выглядят так ), вам обязательно следует взглянуть на jq
, который является довольно полезным инструментом для таких данных.
Если ваши данные выглядят так
{
"db-unique-name": "p00z5bj_iad2bj",
"db-workload": "OLTP",
"defined-tags": {},
"freeform-tags": {},
"id": "dfadfasfsadfasdfasdf",
"lifecycle-details": null,
"lifecycle-state": "AVAILABLE"
}
{
"db-unique-name": "p00u5bh_iad2bj",
"db-workload": "OLTP",
"defined-tags": {},
"freeform-tags": {},
"id": "asdfsadfasdfasfd",
"lifecycle-details": "Resource was terminated at the backend.",
"lifecycle-state": "FAILED"
}
{
"db-unique-name": "p00u5bh_iad2bj",
"db-workload": "OLTP",
"defined-tags": {},
"freeform-tags": {},
"id": "asdfasdfasdf",
"lifecycle-details": "Resource was terminated at the backend.",
"lifecycle-state": "FAILED"
}
то это jq
утверждение
jq 'select(."lifecycle-state" == "AVAILABLE") |."db-unique-name" ' < db_systems.txt
выводит
"p00z5bj_iad2bj"
Однако, если ваш файл на самом деле выглядит как пример, который вы привели (с --
в качестве разделителей и без нотации объекта {} ), тогда решение awk
может быть проще, его довольно сложно впихнуть не -данные JSON в jq...
При таком подходе сначала создается массив, f[]
ниже, который сопоставляет имя каждого элемента с его значением, вы можете получить доступ к каждому полю по его имени и, таким образом, создавать сложные условия и печатать поля в любом порядке:
$ cat tst.awk
{
gsub(/^[[:space:]]*"|"?,[[:space:]]*$/,"")
tag = val = $0
sub(/".*$/,"",tag)
sub(/.*"/,"",val)
f[tag] = val
}
/^--/ { prt() }
END { prt() }
function prt() {
if ( f["lifecycle-state"] == "AVAILABLE" ) {
print f["db-unique-name"]
}
delete f
}
$ awk -f tst.awk file
p00z5bj_iad2bj
Например:
$ cat tst.awk
BEGIN { OFS="," }
{
gsub(/^[[:space:]]*"|"?,[[:space:]]*$/,"")
tag = val = $0
sub(/".*$/,"",tag)
sub(/.*"/,"",val)
f[tag] = val
}
/^--/ { prt() }
END { prt() }
function prt() {
recNr++
if ( (f["lifecycle-state"] == "FAILED") || ( (f["db-unique-name"] ~ /bh/) && (f["db-workload"] == "OLTP") ) ) {
print recNr, f["lifecycle-details"], f["id"], f["db-unique-name"]
}
delete f
}
$ awk -f tst.awk file
2,Resource was terminated at the backend.,asdfsadfasdfasfd,p00u5bh_iad2bj
3,Resource was terminated at the backend.,asdfasdfasdf,p00u5bh_iad2bj
Предполагая, что поля базы данных -уникальное -имя и состояние жизненного цикла -являются обязательными и всегда выводятся в одном и том же порядке (, но не предполагается, что между ними всегда ровно 5 строк )я бы использовал:
cat db_systems.txt \
| grep -E '"(db-unique-name|lifecycle-state)":' \
| grep -B 1 '"AVAILABLE"' \
| grep db-unique-name \
| cut -d\" -f4
Идеально подходит для передачи в xargs
, while read name
и т. д.
Если это фрагменты данных JSON, заверните их обратно в JSON и используйте инструмент JSON.
{ echo '{'; sed 's/^ *-- *$/"": ""} {/' db_systems.txt; echo '"": ""}'; } |
jq 'select(."lifecycle-state" == "AVAILABLE") |."db-unique-name" '
(jq
запрос Ганс -Мартин Моснер)
Это работает:
grep -e db-unique-name -e lifecycle-state.*AVAILABLE < filename | grep -B1 lifecycle-state.*AVAILABLE | grep db-unique-name
В отличие от использования -B6
, это не предполагает наличие 6 строк между двумя интересующими строками.
(Конечно, во многих других ответах справедливо предлагалось использовать jq
, что определенно является лучшим вариантом ).