「key:value」ステートメントの値を変更しますが、ファイルにキーが最初に表示される場合にのみ適用されます。

「key:value」ステートメントの値を変更しますが、ファイルにキーが最初に表示される場合にのみ適用されます。

ymlファイルがあります

spring:
  datasource:
    url: url
    username:test
    password: testpwd
api:
  security:
    username:foo
    password: foopwd

次のように、Linuxシステムでコマンドラインを使用して最初に表示されるユーザー名とパスワードのみを更新したいと思います。

spring:
  datasource:
    url: url
    username:toto
    password: totopsw
api:
  security:
    username:foo
    password: foopwd

私が試したとき:

sed -i -e 's!^\(\s*username:\)[^"]*!\1toto!' test.yml

彼はユーザー名をすべて変更しました

答え1

別のsedオプション:

sed '1,/username/{/username/ s/:.*/:toto/};
     1,/password/{/password/ s/:.*/:totopsw/}' infile

1,/regex/最初の行から始めて、与えられた内容に一致する最初の行までregex(ここでは文字列username)「ユーザー名」を変更し、「パスワード」部分にも同じことを行います。

答え2

ファイルが長い場合、awk1行ずつ処理するためのベースソリューションは次のとおりです。

awk '/^[[:space:]]+username/ && !u_chng{sub(/:.+$/,": toto"); u_chng=1}
     /^[[:space:]]+password/ && !p_chng{sub(/:.+$/,": totospw"); p_chng=1} 1' input.yml 

username各行が個別に開始するかどうかを確認しますpassword。その場合、関連フラグがu_chngまだp_chng設定されていない場合は、次の値を希望する新しい値に設定し、そのキーワードが発生しなくなるように:フラグを設定します。

結果:

spring:
  datasource:
    url: url
    username: toto
    password: totospw
api:
  security:
    username:foo
    password: foopwd

文字クラス()awkを理解していない実装を使用している場合は、次のように変更します。[[:space:]]

/^[[:space:]]+username/

到着

/^[ \t]+username/

答え3

ファイルがメモリに入るのに十分小さい場合は、ファイル全体を単一のレコードとして読み取ることができます。これにより、sedパターンが「行」(レコード)に最初に表示されたときにのみ置換が発生します。

$ sed -Ez 's/(username:)[^\n]*/\1toto/; s/(password:)[^\n]*/\1totopsw/' file.yaml 
spring:
  datasource:
    url: url
    username:toto
    password:totopsw
api:
  security:
    username:foo
    password: foopwd

ソースファイルを変更するには、以下を追加します-i

sed -i -Ez 's/(username:)[^\n]*/\1toto/; s/(password:)[^\n]*/\1totopsw/' file.yaml 

答え4

スクリプトが機能したら、bash次のsed quit コマンドを使用できます。

#!/bin/bash

sed -E '
    # If we find an username
    /username/ {

        # make the sobstitution of the username
        s/^([[:space:]]*username:)/\1toto/g

        n # Take the next line with the password

        # Sobstitute the password
        s/^([[:space:]]*password:).*$/\1totopw/g

        q1 # Quit after the first match
    }
' test.yml > new_test.yml

# How many line we have taken
len_line=$(sed -n '$=' new_test.yml)

# write the other line
sed "1,${len_line}d" test.yml >> new_test.yml

# rename all the file
rm -f test.yml
mv new_test.yml test.yml

関連情報