sshd_config ファイルの末尾には、次のような複数のブロックがあります。
Match User FOO
ChrootDirectory /srv/www/FOO
AllowTCPForwarding no
X11Forwarding no
ForceCommand internal-sftp
Bashスクリプトからこのブロック(FOO1、FOO2などに関連する他のブロックを除く)を削除するにはどうすればよいですか?
答え1
すべてのMatch
ブロックがファイルの末尾にあるとしますsshd_config
。
ブロックが空行で区切られている場合は、次のようになります。
Match User FOO1
PasswordAuthentication no
Match User FOO2
PasswordAuthentication yes
Match User FOO
ChrootDirectory /srv/www/FOO
AllowTCPForwarding no
X11Forwarding no
ForceCommand internal-sftp
Match User FOO
次に、最初の空白行まで(および含む)行から削除します。
sed '/^Match User FOO$/,/^$/d' sshd_config
たとえば、分離されていない場合:
Match User BAZ
PasswordAuthentication yes
Match User FOO
ChrootDirectory /srv/www/FOO
AllowTCPForwarding no
X11Forwarding no
ForceCommand internal-sftp
Match User FOO1
PasswordAuthentication no
Match User FOO2
PasswordAuthentication yes
次に、Match User FOO
次から始まる最初の行まで削除します(含まない)Match
。
sed '/^Match User FOO$/,/^Match.*/{//!d;/^Match User FOO$/d;}' sshd_config
sed -i ...
ファイルの内部編集を使用する必要があります。sed
詳細/バックアップオプションについては、マニュアルを確認してください。
答え2
sendツールとawkツールを使用してこのスクリプトを試すことができます。
matchedLine=$(awk '/Match User FOO1/{ print NR; exit }' $1)
if [ "$matchedLine" = "" ];then
echo "Match not found"
exit 1;
fi
sed -e "$matchedLine,$(awk "BEGIN {print $matchedLine + 5 }";)d;" $1
スクリプトは、SSH 構成ファイルのファイル名を最初の引数として使用します。次に、一致する文字列(この場合は「ユーザーFOO1と一致」)が最初に表示されるかどうかファイルを検索します。一致するものが見つかったら、行番号を$ matchedLine変数に保存します。最後に、sedを使用すると、テキストに一致する行と次の5行が削除されます。このスクリプトは実際のファイルを編集せず、一致する行が削除されたファイルの内容のみを表示します。これにより、リスクなしにスクリプトが正しく機能していることを確認できます。物理ファイルを編集するには、sedコマンドをファイルにリダイレクトするだけです。
答え3
sed '/^Match User FOO$/,/^ *F.*-sftp$/c\
The whole of the above line range is \
replaced with this one block of text.\
Use an empty "c"hange command or a \
"d"elete command to replace it with \
nothing at all.' <infile >outfile
ところで、インデントに頼ることができるようです。たぶんこれを行うことができます:
sed '$!N;/^Match User FOO\n/,/\n[[:upper:]]/!P;D
' <infile >outfile
次の入力ラインを観察しながら、現在のライン削除を開始します。マッチブロックが見つかりました。次の行が大文字で始まる場合は削除を停止します。
上記のコマンドにはより良い説明が必要な場合があります。これが私が知っている最も簡単で信頼できる方法です。
ワークフローは次のとおりです。
!
$
最後の入力ラインではなく、各入力ラインについて、追加のN
入力ラインもパターン空間に追加される。- 通常、一度に1行だけ動作することが知られていますが、
sed
これは基本的な動作です。sed
編集小川必要に応じてカスタマイズできます。 - この場合、
N
extコマンドは次の行を紹介します。視野これは、他の2つのコマンドの助けを借りてスクリプト全体で持続します。
- 通常、一度に1行だけ動作することが知られていますが、
その後、現在のコンテキスト
/2/,/address/
範囲指定された行数です。/^Match User FOO\n/
- 範囲スタート一致するパターンが既に周期のパターン空間にあり、そうでなければP
標準出力として印刷されたとき。これはパターン空間の先頭で表されます。^
アンカーそして\n
パターンの末尾のEwlineです。パターンは、最初から最後までの入力ライン全体を表します。半分いつでもパターン空間。/\n[[:upper:]]/
- これはほとんどの例と例の私の明らかなインデントスタイルに基づいています。sshd_configこれは次のことを示します。みんな関連コマンドの基本要素は大文字で始まります。\n
パターンの先頭 ewline エスケープと組み合わせると、sed
範囲の一致するコンテキストは、ext にインポートされた行が 1 - で始まる場合にのみ終了します。N
いいえスペースが必要です。
範囲内にない場合は、
!
パターン空間のP
最初のewline文字が\n
標準出力として印刷されますが、範囲内にある場合、現在のサイクルでは何も印刷されません。最後に、パターン空間に最初に現れるewlineが
D
削除され、現在のループが終了します。\n
- これは非常に重要です -
D
eleteはそうですいいえ次のサイクルが始まると、新しい入力ラインをドラッグします。〜しない限り\n
現在、パターン空間には0行があります。 - ある時はい
\n
eleteはパターン空間の改行で、D
残りの内容を含む新しいループに再帰される前にその内容までの内容だけを消去します。実際に削除されるのは、範囲と一致しないコンテキストでrintが標準出力に書き込んだ内容D
だけです。P
- これは非常に重要です -
今、これは私が以前に言ったことを言う非常に技術的な方法です。一致範囲の先頭からインデントレベルの終わりまで、行の先頭から大文字で始まる新しいコマンドを見つけることは何もありません。他のすべては印刷中に印刷されます。したがって、ブロックはインデントに応じて非常に簡単な方法で出力から削除され、インデントでのみ選択を制御できます。マッチすでにやったようにブロックしてください。
さて、これらすべてを完全に理解するにはループを理解する必要がありますが、どのように機能するかをsed
詳しくl
見てみるとわかりやすいです。
seq 10 | sed '$!N;/^4\n/,/\n9/!P;l;D'
上記のコマンドは、2つの異なる理由で印刷されます。(該当する場合)範囲一致コンテキストです!P
。これは上記で提案した標準出力です。
第二は、l
それがどのように機能するかについての私たちの理解ですsed
。私はそれを印刷するように言います。すべてループパターン空間の現在の内容を明示的に表現します。結果は次のとおりです。
1 #This is Printed before we look at pattern space.
1\n2$ #This is our look - though only the 1st line is printed,
2 #each time one is, pattern space is actually 2 lines
2\n3$ #all of the time - it's our window into future output.
3
3\n4$ #3 prints, though 4 is in pattern space. But when pattern
4\n5$ #space matches ^4\n as it does now, nothing prints.
5\n6$
6\n7$ #And continues not to print...
7\n8$
8\n9$ #until the range ends here - when \n9 matches our future -
9 #now our current pattern space.
9\n10$
10
10$
これにより、現在のコンテキストでスコープを開始して後で開始できるため、スコープ制御(特別な開始コンテキストと終了コンテキストとそれを制御するための追加の一致が必要なため、一部の人は直感的ではないと思うかもしれません)が全体的に簡単になります。
言い換えれば...
/this_line/,/that_line/command
-次のコマンドの適用 この行まで含める大丈夫
...より視覚的に表現できます...
N;/this_line\n/,/\nthat_line/command;D
-アプリケーションコマンドは次から始まります。この行~まで大丈夫。
\n
これはあなたが期待するほど強力です。これは、編集コマンドに加えて、パターンスペースにewlineを配置する他の方法がないためです。sed
(例:N
拡張)- また、あなたが望むことができる最もパフォーマンスに優れたソリューションの1つです。
だから私はdonのサンプルデータを借りました。
sed '$!N;/^Match User FOO\n/,/\n[[:upper:]]/!P;D' <<\IN
Match User BAZ
PasswordAuthentication yes
Match User FOO
ChrootDirectory /srv/www/FOO
AllowTCPForwarding no
X11Forwarding no
ForceCommand internal-sftp
Match User FOO1
PasswordAuthentication no
Match User FOO2
PasswordAuthentication yes
IN
...そして...
sed '$!N;/^Match User FOO\n/,/\n[[:upper:]]/!P;D' <<\IN
Match User FOO1
PasswordAuthentication no
Match User FOO2
PasswordAuthentication yes
Match User FOO
ChrootDirectory /srv/www/FOO
AllowTCPForwarding no
X11Forwarding no
ForceCommand internal-sftp
Match User FOO2
PasswordAuthentication yes
IN
...印刷されます...
Match User BAZ
PasswordAuthentication yes
Match User FOO1
PasswordAuthentication no
Match User FOO2
PasswordAuthentication yes
...そして...
Match User FOO1
PasswordAuthentication no
Match User FOO2
PasswordAuthentication yes
Match User FOO2
PasswordAuthentication yes
...それぞれ。
ただし、空行では範囲コンテキストを終了しません。ブロックの後の空白行は、作成中のブロックの一部と見なされます。したがって、第2の例では、出力行間のスペースはその前のスペースである。たとえば、次のようになります。
sed '$!N;/^Match User FOO\n/,/\n\([[:upper:]].*\)*$/!P;D' <infile >oufile
...これは、範囲コンテキストを破壊し、大文字で始まる空行で出力書き込みを再開します。さらに、次のような場合がより一般的になる可能性があります。
sed '$!N;/^Match User FOO\n/,/\n\([^[:blank:]].*\)*$/!P;D' <infile >oufile
...これにより、空白行や空白以外の文字で開いた行の範囲が中断されます。すべての場合において、ブレイクアウトパターンは再開したいパターンであり、停止したい一連のパターンのうち最後のパターンではありません。
答え4
しかし、sedは可能です、awkで強力にする方が簡単です。次のスクリプトは、Match User FOO
(または大文字と小文字とスペースのバリエーション)で始まる行をスキップし、他の行ではスキップを停止Match User
し、スキップされていないすべての行を印刷します。
awk '
tolower($1)=="match" && tolower($2) == "user" {skip = $3 == "foo"}
!skip
'
スクリプトが中断された場合は、出力を一時ファイルに書き込み、その場所に移動します。他の人が同時にファイルを変更すると、データが失われる可能性があります。
awk … </etc/sshd_config >/etc/sshd_config.tmp &&
mv /etc/sshd_config.tmp /etc/sshd_config