
以下の詳細を含むヒューファイルがあります。
define host{
use generic-host ; Name of host template to use
host_name ServerA_172.29.16.102
alias ServerA_172.29.16.102
address 172.29.16.102
check_command check-host-alive
max_check_attempts 3
notification_interval 120
notification_period 24x7
}
define host{
use generic-host ; Name of host template to use
host_name ServerB_172.29.16.103
alias ServerB_172.29.16.103
address 172.29.16.103
check_command check-host-alive
max_check_attempts 3
notification_interval 120
notification_period 24x7
}
私が望むのは、"address 172.29.16.102"
5行上、4行後の4行を見つけて削除することです。
sedを試しましたが、うまくいきません
sed '$N;$N;N;/address 172.29.16.102/,+5d' hosts
答え1
これは、各define_host
部分が1つ以上の改行で区切られている場合、GNU awkで発生する問題の種類とまったく同じです。複数行のレコードサポートは解決のためである
awk -v RS= '!/172.29.16.102/{printf $0""RT}'
答え2
このような質問を見ると直感的にこれが職業だと思いますgrep
。ただし、前方および後方のスイッチ(&)を使用するときに結果を反転()する機能はgrep
これを許可しません。-v
-B ..
-A ..
grep
しかし、これを2回呼び出すこの賢いアプローチは、これまでに見たソリューションよりawk
はるかにきれいです。sed
$ grep -v "$(grep -B 4 -A 5 'address 172.29.16.102' <file>)" <file>
はい
以下は、いくつかのサンプルデータです。
$ cat sample.txt
define host{
use generic-host ; Name of host template to use
host_name ServerA_172.29.16.102
alias ServerA_172.29.16.102
address 172.29.16.102
check_command check-host-alive
max_check_attempts 3
notification_interval 120
notification_period 24x7
}
line1b
line2b
line3b
line4b
address 172.29.16.102
line5a
line4a
line3a
line2a
line1a
define host{
use generic-host ; Name of host template to use
host_name ServerB_172.29.16.103
alias ServerB_172.29.16.103
address 172.29.16.103
check_command check-host-alive
max_check_attempts 3
notification_interval 120
notification_period 24x7
}
次のコマンドを実行すると、
$ grep -v "$(grep -B 4 -A 5 'address 172.29.16.102' sample.txt)" sample.txt
define host{
use generic-host ; Name of host template to use
host_name ServerA_172.29.16.102
alias ServerA_172.29.16.102
address 172.29.16.102
check_command check-host-alive
max_check_attempts 3
notification_interval 120
notification_period 24x7
}
define host{
use generic-host ; Name of host template to use
host_name ServerB_172.29.16.103
alias ServerB_172.29.16.103
address 172.29.16.103
check_command check-host-alive
max_check_attempts 3
notification_interval 120
notification_period 24x7
}
答え3
sed
理由の完璧な例は次のとおりです。Sトレメ編集するex
itorであり、内部ファイル編集機能を決して置き換えません。
ex -c '/address *172.29.16.103/
?{?,/}/d
x' input
このコマンドは単純化された形式であり、強力ではありませんが、説明のために使用されます。
最初のコマンドは指定された正規表現を探し、カーソルをその行に移動します。
2番目のコマンドは、d
eleteコマンドが実行される2つのカンマ区切りアドレスで構成されています。 ?{?
現在の行で後方に開く中括弧を検索し、/}/
現在の行で前方に閉じている中かっこを検索します。その間のすべての内容が削除されます(1行ずつ、開いた中括弧行の先頭も削除されます)。
x
変更を保存して終了します。もちろんinput
ファイル名です。
このコマンドは、入力した入力に対して期待どおりに正しく機能します。
今、私はこれが大幅に改善できると述べました。正規表現から始めます。ここで最も顕著な特徴は、ピリオドがワイルドカード文字であることです。与えられた正規表現は「172329-16 103」とも一致できます。したがって、ピリオドはリテラルピリオドとのみ一致するようにバックスラッシュでエスケープする必要があります。
以下は空白です。 2つのスペースの後に*があります(使用できますが、\+
POSIXにその機能が必要かどうかは不明です)。ファイルにタブがあるとどうなりますか?最良の解決策はを使用することです[[:space:]]
。 (これは良く見えます\+
。これがPOSIXであるかどうかを調べた人がいる場合は、コメントを残してください。)
最後に、正規表現が次のような場合いいえファイルで見つかりましたか?これにより、ファイルが編集用に開かれ、「検索」コマンドが失敗し、エラーメッセージが表示され、指定されたコマンドの残りの部分は実行されません。エディタに残って検索できますex
。手動で変更されます。ただし、スクリプトの編集を自動化するにはエディタが必要な場合があります。出口変更が必要ない場合。答えはg
グローバルコマンドを使用し、この-s
フラグを使用してすべての出力を抑制することですex
。
ex -sc 'g/address[[:space:]][[:space:]]*172\.29\.16\.103/ ?{?,/}/d
x' input
これはないかなり前のコマンドと同じです。一致する行がある中括弧ブロックが複数ある場合、ここのグローバルコマンドはそのブロックをすべて削除します。とにかく、これはおそらくあなたが望むものです。
最初の一致のみを削除し、一致がまったくない場合にファイルを変更せずに終了するには、このコマンドをコマンド引数x
の一部として使用しg
(最初の削除コマンドを実行してファイルを終了し)、次のq!
場所にコマンドを追加します。g
一致する行がないため、コマンドが実行されない場合に備えて下部に表示されます。
ex -sc 'g/address[[:space:]][[:space:]]*172\.29\.16\.103/ ?{?,/}/d | x
q!' input
正直なところ、これらのコマンドはプロセスを実際よりもはるかに複雑に見せます。堅牢性は、コードの極端な明確性と可読性を犠牲にして発生します。これは妥協案です。
ex
感じを得るには、一部のファイルを対話形式で編集することをお勧めします。だからあなたはできますバラより何をしてください。この修正を対話的に実行する編集セッションはex
次のとおりです。
$ ex input
"input" 23L, 843C
Entering Ex mode. Type "visual" to go to Normal mode.
:/103
host_name ServerB_172.29.16.103
:?{?,/}/d # This deletes the current block
:$p # Print and move to last line
:-5,.p # Print some more lines to check result
notification_interval 120
notification_period 24x7
}
:?}?+,.d # Trim whitespace
}
:x # Save and exit
$
これPOSIX仕様ex
追加資料が提供されます。
答え4
これはどうですか?
egrep -v '^([[:space:]]+(use|host_name|alias|check_command|max_check_attempts|notification_interval|notification_period)[[:space:]]+|^define host{|^[[:space:]]+})'
ファイルに同様の行がないと仮定すると、不要な特定の行を削除します。