次の行を追加するために、次のsed cliを構築しました。
force_https_protocol=PROTOCOL_TLSv1_2
ラインの後ろ:
[security]
sed コマンドラインインタフェース:
sed -i '/\[security\]/a force_https_protocol=PROTOCOL_TLSv1_2' /etc/ambari-agent/conf/ambari-agent.ini
しかし、問題は - 行がforce_https_protocol=PROTOCOL_TLSv1_2
すでに後ろにあるときです。[security]
すでに存在する場合は、行の追加を無視するようにsed構文をどのように変更できますか?
期待される出力
[security]
force_https_protocol=PROTOCOL_TLSv1_2
keysdir=/var/lib/ambari-agent/keys
server_crt=ca.crt
passphrase_env_var_name=AMBARI_PASSPHRASE
無効なファイル:
[security]
force_https_protocol=PROTOCOL_TLSv1_2
force_https_protocol=PROTOCOL_TLSv1_2
keysdir=/var/lib/ambari-agent/keys
server_crt=ca.crt
passphrase_env_var_name=AMBARI_PASSPHRASE
答え1
ファイル内のすべての「force_https_protocol=PROTOCOL_TLSv1_2」が[security]タグ内にあり、他の場所には表示されないとします。
sed -e '/^force_https_protocol=PROTOCOL_TLSv1_2$/d'\
-e '/\[security\]/a force_https_protocol=PROTOCOL_TLSv1_2' file
アイデアは、文字列 "force_https_protocol=PROTOCOL_TLSv1_2"のみを含むファイルのすべての行を削除することです。
説明する
/^force_https_protocol=PROTOCOL_TLSv1_2$/d'
"force_https_protocol=PROTOCOL_TLSv1_2" 文字列を含むすべての行を削除します。
テスト
$ cat file
[security]
force_https_protocol=PROTOCOL_TLSv1_2
keysdir=/var/lib/ambari-agent/keys
server_crt=ca.crt
passphrase_env_var_name=AMBARI_PASSPHRASE
[security]
keysdir=/var/lib/ambari-agent/keys
server_crt=ca.crt
passphrase_env_var_name=AMBARI_PASSPHRASE
$ sed -e '/^force_https_protocol=PROTOCOL_TLSv1_2$/d'\
-e '/\[security\]/a force_https_protocol=PROTOCOL_TLSv1_2' file
[security]
force_https_protocol=PROTOCOL_TLSv1_2
keysdir=/var/lib/ambari-agent/keys
server_crt=ca.crt
passphrase_env_var_name=AMBARI_PASSPHRASE
[security]
force_https_protocol=PROTOCOL_TLSv1_2
keysdir=/var/lib/ambari-agent/keys
server_crt=ca.crt
passphrase_env_var_name=AMBARI_PASSPHRASE
答え2
1. AWKを使用
より一般的な問題を追加する可能な解決策は次のとおりです。ひも場合のみひもまだ表示されていません。
簡単なアプローチは、ファイルを後ろに移動して、最後に発生した時点を追跡することです。ひも、特定のラベルが表示されるたびに(ラベル自体を印刷する直前)印刷するが、まだ見たことがない場合にのみ(ひも)しかし遭遇するのを忘れてください(ひも)タグに会うたびに。もちろん、最後のステップは結果を反転することです。
tac file | awk '
/^force_https_protocol=PROTOCOL_TLSv1_2$/ {
seen = 1
}
/^\[security\]$/ {
if ( ! seen ) {
print "force_https_protocol=PROTOCOL_TLSv1_2"
}
}
/^\[[^]]*\]$/ {
seen = 0
}
1' | tac
tac
、含まれるGNU Coreutils、ファイルを 1 行ずつリンクし、逆方向にします。 U&Lの複数のQ&Aでは、ギター/標準ツール(例:コマンド sed '1!G;h;$!d' ファイルの内容をどのように戻しますか?そしてリバースのインポート)。
force_https_protocol=PROTOCOL_TLSv1_2
次のテキストスニペットの最初の部分の後には挿入されません。[security]
[security]
keysdir=/var/lib/ambari-agent/keys
force_https_protocol=PROTOCOL_TLSv1_2
passphrase_env_var_name=AMBARI_PASSPHRASE
[security]
...
ただ挿入してくださいひもラベルが表示されるたびにひもすでに存在しているのと同じアプローチで、次のことが発生する可能性があります。
tac file | awk '
/^force_https_protocol=PROTOCOL_TLSv1_2$/ {
seen = NR
}
/^\[security\]$/ {
if ( ( NR == 1 ) || ! ( NR == seen + 1 ) ) {
print "force_https_protocol=PROTOCOL_TLSv1_2"
}
}
1' | tac
(これ〜する上記のテキストの例の後に挿入してくださいforce_https_protocol=PROTOCOL_TLSv1_2
。)[security]
2. sedを使う
sed
さまざまなループが利用可能です(N;P;D;
U&Lの他のQ / Aでこれを広く扱っています。例:sedを使用して複数行の文字列を置き換える方法は?またはsedを使用してパターンの後の次の行を編集するには?)。
その行は、前の行がまだ存在しない場合force_https_protocol=PROTOCOL_TLSv1_2
にのみ構成された行の後に挿入されます。[security]
sed '
$! {
N
P
/^\[security\]\n/ {
/\nforce_https_protocol=PROTOCOL_TLSv1_2$/ b b
i\
force_https_protocol=PROTOCOL_TLSv1_2
}
:b
D
}
s/^\[security\]$/&\
force_https_protocol=PROTOCOL_TLSv1_2/'
このスクリプトは次のとおりです。
- 最後の行()を除く各行に、改行文字
$!
と次の行をパターンスペース(N
)(現在の行が含まれている)に追加します。 P
その行が次の場合は、パターンスペース()の最初の行を印刷します[security]
。- ...次の行はです
force_https_protocol=PROTOCOL_TLSv1_2
。パターンスペースから最初の行を削除して新しいループ(b b
、、:b D
)を開始します。 - それ以外の場合は、パターンスペースから最初の行を削除し、新しいループを開始する前に
force_https_protocol=PROTOCOL_TLSv1_2
標準出力()として印刷します()。i\
D
- ...次の行はです
- 最後の行がある場合は
[security]
、その行をそれ自体に置き換え、その後に改行を追加してforce_https_protocol=PROTOCOL_TLSv1_2
結果を印刷します(暗黙的にp
)。