web-dev-qa-db-ja.com

一致する検索値に基づいて特定の値をgrepする方法

"db-unique-name"が含まれるlifecycle-state": "AVAILABLE"の検索についてサポートが必要です。

cat db_systems.txt

     "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",
    enter code here

"db-unique-name"に基づいて"lifecycle-state": "AVAILABLE"の値を試しました。次、しかしそれは間違った値を与えます

cat db_systems.txt  |  egrep -A -6  "lifecycle-state|AVAILABLE" | grep  db-unique-name
"db-unique-name": "p00u5bh_iad2bj",
"db-unique-name": "p00u5bh_iad2bj",

私もこれを試しましたが、すべてがリストされています

cat db_systems.txt |  awk -F";" '{for(i=1;i<=NF;i++){if ($i ~ /AVAILABLE|db-unique-name/){print $1}}}' | grep db-unique-name
"db-unique-name": "p00z5bj_iad2bj",
"db-unique-name": "p00u5bh_iad2bj",
"db-unique-name": "p00u5bh_iad2bj",
5
CoolChap007

これを試して、

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",
3
Siva

GNU awk

awk -F',' 'BEGIN { RS = "--" } /"lifecycle-state": "AVAILABLE"/ {  gsub("^[[:blank:]]*", "", $1);  print $1 }' file

出力:

"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ソリューションの方が簡単かもしれません。

4

これはうまくいくはずです:

$ 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",
3
terdon

これらがJSONデータの抽出である場合は、それらをJSONにラップして、JSONツールを使用します。

{ echo '{'; sed 's/^ *-- *$/"": ""} {/' db_systems.txt; echo '"": ""}'; } |
jq 'select(."lifecycle-state" == "AVAILABLE") | ."db-unique-name" '

jq query by Hans-Martin Mosner

最初に配列を作成するこのアプローチでは、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
2
Ed Morton

Db-unique-nameフィールドとlifecycle-stateフィールドが必須であり、常に同じ順序で出力されると想定します(ただし、間に正確に5行あるとは限りません)。

cat db_systems.txt \
  | grep -E '"(db-unique-name|lifecycle-state)":' \
  | grep -B 1 '"AVAILABLE"' \
  | grep db-unique-name \
  | cut -d\" -f4

xargswhile read nameなどにパイプするのに最適です。

0
thsutton

これは役に立ちます。

grep -B 6 AVAILABLE db_systems.txt | grep db-unique-name
0
binarysta

これは機能します:

grep -e db-unique-name -e lifecycle-state.*AVAILABLE < filename | grep -B1 lifecycle-state.*AVAILABLE | grep db-unique-name

-B6を使用する場合とは異なり、これは対象の2行の間に6行あることを想定していません。

(もちろん、他の多くの応答はjqを使用することを正しく提案しています。これは間違いなくより良いオプションです)。

0
sitaram