次のようなファイル(file.php
)があります。
...
Match user foo
ChrootDirectory /NAS/foo.info/
ForceCommand internal-sftp
AllowTcpForwarding no
GatewayPorts no
X11Forwarding no
Match user bar
ChrootDirectory /NAS/bar.co.uk/
ForceCommand internal-sftp
AllowTcpForwarding no
GatewayPorts no
X11Forwarding no
Match user baz
ChrootDirectory /NAS/baz.com/
ForceCommand internal-sftp
AllowTcpForwarding no
GatewayPorts no
X11Forwarding no
段落の1つを削除するbashスクリプトを作成しようとしています。
つまり、ユーザーfoo
をfile.php
から削除したいとします。スクリプトを実行すると、次のようになります。
...
Match user bar
ChrootDirectory /NAS/bar.co.uk/
ForceCommand internal-sftp
AllowTcpForwarding no
GatewayPorts no
X11Forwarding no
Match user baz
ChrootDirectory /NAS/baz.com/
ForceCommand internal-sftp
AllowTcpForwarding no
GatewayPorts no
X11Forwarding no
どうすればこれを実行できますか? sed
を使用することを考えましたが、それは1つのライナーにのみ適切であると思われますか?
sed -i 's/foo//g' file.php
そして、段落を含むほとんどの行は一意ではないので、個々の行ごとにそれを行うことはできませんでした!何か案は?
実際には、sed
も範囲を取ることができます。このコマンドは、Match user foo
と最初の空の行(両端を含む)の間のすべての行を削除します。
$ sed '/Match user foo/,/^\s*$/{d}' file
Match user bar
ChrootDirectory /NAS/bar.co.uk/
ForceCommand internal-sftp
AllowTcpForwarding no
GatewayPorts no
X11Forwarding no
Match user baz
ChrootDirectory /NAS/baz.com/
ForceCommand internal-sftp
AllowTcpForwarding no
GatewayPorts no
X11Forwarding no
ただし、個人的には、Perlの段落モード(-00
)を使用してこれを行います。これには、先頭の空白行を削除するという利点があります。
$ Perl -00ne 'print unless /Match user foo/' file
Match user bar
ChrootDirectory /NAS/bar.co.uk/
ForceCommand internal-sftp
AllowTcpForwarding no
GatewayPorts no
X11Forwarding no
Match user baz
ChrootDirectory /NAS/baz.com/
ForceCommand internal-sftp
AllowTcpForwarding no
GatewayPorts no
X11Forwarding no
どちらの場合も、-i
を使用してファイルを編集できます(これにより、元のfile.bak
のバックアップが作成されます)。
sed -i.bak '/Match user foo/,/^\s*$/{d}' file
または
Perl -i.bak -00ne 'print unless /Match user foo/' file
Terdonのsed
回答よりも少し複雑です:
awk '/foo/ {suppress=1} /^\s*$/ {suppress=0} !suppress' file.php
terdonの答えとほぼ同じ結果が得られます。
...
Match user bar
ChrootDirectory /NAS/bar.co.uk/
ForceCommand internal-sftp
AllowTcpForwarding no
GatewayPorts no
X11Forwarding no
Match user baz
ChrootDirectory /NAS/baz.com/
ForceCommand internal-sftp
AllowTcpForwarding no
GatewayPorts no
X11Forwarding no
つまり、foo
up toに一致する行で始まるすべての行を削除(抑制)します。これは、空白のみを含む最初の後続行です。 file.php
入力ファイル(user foo
とuser bar
の間)で空白の行8、9、および10が出力に出力されます。対照的に、terdonの回答は、foo
up throughに一致する行で始まるすべての行を削除します。空白のみを含む最初の後続行。したがって、8行目は削除されますが、9と10は通過します。
これらは、ユーザーが要求したものとは正確には異なります。
awk '/foo/ {suppress=1}
/^\s*$/ && suppress==1 {suppress=2}
/[^\s]/ && suppress==2 {suppress=0}
!suppress' file.php
です。 (これは読みやすくするために複数の行に分割されています。1行ですべて入力できます。)foo
が見つかると、抑制モード#1(suppress=1
)になります。抑制モード#1で空白行が表示されると、抑制モード#2に切り替わります。抑制モード#2で空白以外の行が表示されると、モード0に切り替わります。最後に、suppress
edされていない行を出力します。