次のセクションを含むYAMLファイルがあります。
admin::common::passwords:
alice:
password: '$6$oTQhLvN/4VFJPscD$8LYwUMSFi'
bob:
password: '$6$JKOtLF0wHeZfIskt$W/M5.ugDS'
シェル変数$ ACCOUNTにアカウント名(alice、bobなど)が含まれていて、$ YAMLがYAMLファイルのファイル名である場合は、次のようにsedを使用して新しいエントリを追加できます。 "admin::common::passwords:" 行の直下に新しいアカウントが挿入されるので、そのアカウントが正しいセクションにあることがわかります。
sed -i /'^admin::common::passwords:'/a"\ ${ACCOUNT}:\n password: '${ENCRYPTED_PASS}'" $YAML
awkを使用して、このような既存のアカウントを見つけることができます。今回もセクションを見つけて、そのセクション内のアカウントを見つけます(awkでこれを行うことは可能かもしれませんが、awkでは十分ではないのでこれを行います)。
awk "BEGIN{RS=ORS="\n\n";FS=OFS="\n"}/admin::common::passwords:/" $YAML | grep -A1 "^[ ]*${ACCOUNT}:"
しかし、行を削除するには、私が考えることができる最善の方法は次のとおりです。
sed -i "/^ ${ACCOUNT}:/,+1d" $YAML
これにより、admin::common::passwords セクションか他の場所にあっても、ファイル内のすべての "^alice:" 行が削除されます。
ファイルに admin::common:passwords セクションが含まれていること以外は、ファイルの内容について何の前提もできません(そうでなければ、私のスクリプトの他の部分によって生成されます。そのビットは単純です)。
だから私の質問は:sedの面でこれをどのように改善できますか?"^${ACCOUNT}:" 検索admin::common::passwords セクションでをタップして、一致する行とその下の行を削除します。'?
(もちろん、sedを使用する必要はありません。awkまたはPerlが作業に適している可能性もあります。)
ベストアンサー1
sed "
/^admin::common::passwords:$/,/^[^ ].*:$/ {
/^ $ACCOUNT:$/ {
N;d
}
}" < "$YAML"
つまり、削除されたセクションをadmin::common...
次のセクションと一致するセクションに含めますwhatever-section:
。
ユーザー名によく使われる文字.
も正規表現演算子なので、とjohn.doe
一致john.doe
するjohnWdoe
が、例えば。
admin::common::passwords
2つの連続したセクションがあり、削除するアカウントが2番目のセクションにある場合、上記の方法は機能しません。
もし、オシウスが指摘したように、セクションは、同じまたはより少ない先行スペース文字を使用して次の行で実行され、セクションにadmin::common::passwords:
先行スペースがある可能性があります。これにより、他の言語に切り替える必要がある場合がありますawk
。たとえば、次のようになります。
awk -v account="$ACCOUNT" '
match($0, /[^ ]/) && RSTART <= n {n = 0}
n && NF == 1 && $1 == account ":" {getline; next}
!n && /^ *admin::common::passwords:$/ {
match($0, /[^ ]/)
n = RSTART
}
{print}' < "$YAML"