複数のセクションを持つファイルの1つのセクションで文字列を検索する

複数のセクションを持つファイルの1つのセクションで文字列を検索する

sed / awkを使用して他の文字列に含まれる文字列を取得する方法。

TESTVAR='
{
 icon : "icons/773_l.png",
 id : 80,
 initialState : true,
 isPng : false,
 label : "Imagery",
 opacity : 1,
 requestType : "UUID",
 version : 79
}
,
{
 icon : "thisicon",
 id : 8080,
 initialState : false,
 isPng : true,
 label : "Boundaries",
 opacity : 1,
 requestType : "NothingSpecial",
 version : 8
}

version : 79埋め込みオブジェクトを選択する必要がありますrequestType : "UUID"。最初のブロック内のすべての項目を選択してバージョンを選択し、returnコマンドを使用するにはどうすればよいですか79?私はこれをしばらく試してきましたが、最初のものの間ですべてを選択する方法を知りません{}。これを行ったら、次に番号を見つけてくださいversion :

私はこれがうまくいくと思いましたが、そうではありませんでしたawk '/\{/{f=1;next}/\}/{f=0}f' test.txt

また、注文は保証されません。したがって、「UUID」を含む{すべての項目を選択する必要があります}。それから選択version : \([0-9]+\)

これは近いですが、あまりにも貪欲です。sed -e 's/{\(.*UUID.*\)}/\1/' test.txt

答え1

私の心に最初に浮かんだのはsedでもawkでもありませんでした。

$ tr -d '\n' < file | grep -Po 'requestType : "UUID"\K.*? version : \K[0-9]*'
79

おそらくもっと簡単にできるでしょう。特に、「requestType」の直後に「version」が来ることを保証できれば、さらにそうです。

状況をもう少し複雑にversionする必要がない場合は、次のようにします。requested Type

$ tr -d '\n' < file | grep -Po '{.[^}]*?requestType : "UUID".*?}' | grep -Po 'version : \K[0-9]*'
79

すべての部品に一致できる部品があれば印刷されます。

$ cat file
TESTVAR='
{
 icon : "icons/773_l.png",
 id : 80,
 initialState : true,
 isPng : false,
 label : "Imagery",
 opacity : 1,
 version : 79,
 requestType : "UUID"
}
,
{
 icon : "thisicon",
 id : 8080,
 initialState : false,
 isPng : true,
 label : "Boundaries",
 opacity : 1,
 requestType : "NothingSpecial",
 version : 8
}
,
{
 icon : "icons/773_l.png",
 id : 80,
 initialState : true,
 isPng : false,
 label : "Imagery",
 opacity : 1,
 requestType : "UUID",
 version : 87
}
,
{
 icon : "icons/773_l.png",
 id : 80,
 version : 17,
 initialState : true,
 isPng : false,
 label : "Imagery",
 opacity : 1,
 requestType : "UUID"
}
,
{
 icon : "thisicon",
 id : 8080,
 requestType : "NothingSpecial",
 initialState : false,
 label : "Boundaries",
 opacity : 1,
 version : 18,
 isPng : true
}

$ tr -d '\n' < file | grep -Po '{.[^}]*?requestType : "UUID".*?}' | grep -Po 'version : \K[0-9]*'
79
87
17

答え2

awkではレコード区切り文字を定義できます。改行(各行はレコードです)を使用する代わりに、レコードの末尾に「} \ n」を使用してください。

echo "$TESTVAR" |
gawk -v RS="}\n" '
    /requestType : "UUID"/ && match($0, /version : ([0-9]+)/, m) {print m[1]}
'
79

これはGNU awkに固有のものであり、match()関数で使用されます。


残念ながら、これは有効なJSONではありません。その後、JSONパーサーを使用できます。

jq '(.[] | select(.requestType == "UUID")).version' <<JSON
[
 {
  "icon" : "icons/773_l.png",
  "id" : 80,
  "initialState" : true,
  "isPng" : false,
  "label" : "Imagery",
  "opacity" : 1,
  "requestType" : "UUID",
  "version" : 79
 }
 ,
 {
  "icon" : "thisicon",
  "id" : 8080,
  "initialState" : false,
  "isPng" : true,
  "label" : "Boundaries",
  "opacity" : 1,
  "requestType" : "NothingSpecial",
  "version" : 8
 }
]
JSON

答え3

以下は、純粋に以下を使用して実行する1つの方法ですsed

$ sed -rn '/\{/{:a;N;/\}/{/requestType : "UUID"/s/.*version : ([0-9]+).*/\1/p;d};ba}' <<< "$TESTVAR"
79
$ 

これは以下で適応された。https://stackoverflow.com/a/18046021/2113226あなたのデータのため。


これがJavaScriptデータ構造であると言われましたが、これを解析する最も信頼できる方法はJavaScriptを使用することです。これを行うには、Node.jsをインストールしましたが、すべてのコマンドラインJavaScriptインタプリタは、次のことができる必要があると思います。

$ echo "arr=[$TESTVAR]; console.log(arr.filter(function(elem) { return elem.requestType === \"UUID\"; })[0].version)" | node
79
$ 

婦人声明

ここでデータを安全に保管する必要があります。 JavaScriptについてはよくわかりませんが、入力データ文字列を正しく制作すれば、コードインジェクションは完全に可能であると思います。

関連情報