外部ツールを使用せずにyamlファイルを解析する

外部ツールを使用せずにyamlファイルを解析する

私はBashを初めて使用するときにyamlファイルでいくつかの動的パラメータを更新する必要があるという問題に遭遇しました。

クエリ()によると、search4.subsearch1.name更新する必要があります。

name: old_name

入力する

name: new_name
  • サンプルファイルは次のとおりです。
    search1:
        name: name1
        pass: pass1
        date: date1
    #these are just commented texts
    
    search2:
      #Adding few more commented lines
        myname: somename
        name: name2
        pass: pass2
        someotherparam: param1
    
    search3:
        nameAndSurname: NS
        namingConv: true
        varSet: P3
    
    search4:
        #Again adding some special name: strings here
            myname: somename1
            name: new_name
            pass: new_pass
            ptherparam1: T3
    
        subsearch1:
            #Again adding some special name strings here
                myname: somename2
                name: old_name
                pass: pass2
                ptherparam1: param3
    search5:
        #Again adding some special name strings here
            var1: value1
            name: some_name
            pass: some_pass
    

したがって、クエリ()に基づいて次にsearch4.subsearch1.name更新する必要があります。name: old_namename: new_name

  • 予想出力:
    search4:
        #Again adding some special name: strings here
            myname: somename1
            name: new_name
            pass: new_pass
            ptherparam1: T3
    
        subsearch1:
            #Again adding some special name strings here
                myname: somename2
                name: new_name
                pass: pass2
                ptherparam1: param3
    

試してみましたがawk成功sedしませんでした。

lineNR=$(awk "/\<search4:/{f=1} f && /\<name:/ {print NR; exit}" testfile.txt);sed "${lineNR}s/name.*/name: new_name/" testfile.txt

答え1

あなたが持つことができると仮定マイクパラyqダウンロードしてインストールすると、プロセスが簡単になります。

yq eval '.search4.subsearch1.name = "new_name"' file.yml

私はあなたが言ったことに気づきました。コメントそれ」私たちはインターネットに接続されておらず、対応するLinuxボックスには外部パッケージは許可されていません。自分自身がパッケージを追加できない場合でも、これらのシステムにソフトウェアを追加するように要求する管理プロセスがあります。「変更要求」かもしれません。サポートしやすい


テストのためにインデントが入っていることを確認するためにコンテンツを編集する必要がありましたsearch4。質問自体の内容を編集したわけではありません。

答え2

どのシステムを使用しているのか、インストールしたのか教えてくれませんでした。したがって、これは単に教育された推測です。多くのLinuxディストリビューションには「python」が付属しており、yamlの増加は、このディストリビューションが「pyaml」ライブラリとともにインストールされることが多いことを意味します。 yamlファイルと直接対話するという事実は、このシナリオの可能性を高めます。

これを非常に簡単にテストできます。次の内容のみを含むファイルを作成しますfoo.py

import yaml
print("I have yaml")

次に、コマンドラインから実行します。

python3 foo.py

単に印刷する場合は、pythonとpyamlがインストールされており、単純なスクリプト()I have yamlで使用できます。update_script.py

import yaml
import sys

# Load the file into a data structure
with open(sys.argv[1], "r") as file:
    content = yaml.safe_load(file)

# Update the key you want to change
content["search4"]["subsearch1"]["name"] = "new_name"

# Write the data structure back to your file in YAML
with open(sys.argv[1], "w") as file:
    yaml.safe_dump(content, file)

次に、次を実行します。

python3 update_script.py config_file.yaml

答え3

すべてのUnixシステムのすべてのシェルでawkを使用してください。

$ cat tst.awk
NF && !/^[[:space:]]*#/ && match($0,/^[[:space:]]*/) {
    prevIndent = currIndent
    currIndent = RLENGTH

    name = $1
    sub(/:.*/,"",name)

    if ( currIndent == 0 ) {
        path = name
    }
    else {
        if ( currIndent <= prevIndent ) {
            sub(/\.[^.]+$/,"",path)
        }
        path = path "." name
    }

    if ( path == tgt ) {
        $0 = substr($0,1,currIndent) $1 " " val
    }
}
{ print }

$ awk -v tgt='search4.subsearch1.name' -v val='new_name' -f tst.awk file
search1:
    name: name1
    pass: pass1
    date: date1
#these are just commented texts

search2:
  #Adding few more commented lines
    myname: somename
    name: name2
    pass: pass2
    someotherparam: param1

search3:
    nameAndSurname: NS
    namingConv: true
    varSet: P3

search4:
    #Again adding some special name: strings here
        myname: somename1
        name: new_name
        pass: new_pass
        ptherparam1: T3

    subsearch1:
        #Again adding some special name strings here
            myname: somename2
            name: new_name
            pass: pass2
            ptherparam1: param3
search5:
    #Again adding some special name strings here
        var1: value1
        name: some_name
        pass: some_pass

上記はYAMLパーサーではなく、表示された例と同じ構造を持つファイルに対してのみ機能し、すべてのインデントはタブまたはスペースですが、両方ではありません。

バラよりhttps://stackoverflow.com/questions/66173552/update-yaml-value-on-cli#comment116993514_66173552上記の他のアプリケーションの場合。

関連情報