ここに別のものがありsedます:
sed -e:n -e'/\n#.*\ndotan/!{$!{N;/^#/bn' \
-eb -e\} -e'/^#/s/\(\n\)\(dotan.*\)*/\1#\2/g' \
-et -e\} -eP\;D <in >out
あなたが尋ねるとおりです。それは単にスタック上で動作します-必要に応じて、コメント行が発生する間、必要に応じてそれを構築し、入力が見つかったときに入力で新しいコメント行を優先して古いバッファをダンプします。画像...

申し訳ありませんが、なぜそうしたのかわかりません。しかし、それは思い浮かびました。
とにかく、sedすべてのシリーズの最後にコメントされた行の間にバッファーを広げ、最後にコメントされた発生を正確に追跡するために必要なよりも単一のバッファーをバッファに保持することはありません。最終的なgローブ実行ステートメントとブランチtは、バッファ全体を出力します。それ以外の場合はP、バッファから解放されるすべての行をリントします。
これがアコーディオンを思い起こさせたものだと思います...
printf %s\\n \#alice \#bob charlie dotan eric \
\#alice \#bob charlie dotan eric \
\#alice \#bob charlie dotan eric |
sed -e:n -e'l;/\n#.*\ndotan/!{$!{N;/^#/bn' \
-eb -e\} -e'/^#/s/\(\n\)\(dotan.*\)*/\1#\2/g' \
-et -e\} -eP\;D
#alice
#alice\n#bob$
#alice\n#bob\ncharlie$
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob\ncharlie\ndotan\neric\n#alice$
#bob\ncharlie\ndotan\neric\n#alice\n#bob$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
#bob
charlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
charlie
dotan\neric\n#alice\n#bob\ncharlie\ndotan$
dotan
eric\n#alice\n#bob\ncharlie\ndotan$
eric
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob\ncharlie\ndotan\neric\n#alice$
#bob\ncharlie\ndotan\neric\n#alice\n#bob$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
#bob
charlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
charlie
dotan\neric\n#alice\n#bob\ncharlie\ndotan$
dotan
eric\n#alice\n#bob\ncharlie\ndotan$
eric
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob
#charlie
#dotan
eric
このコマンドと上記のコマンドの違いは1つだけlです。これは上部のookコマンドです。動作するのパターンスペースにl注目sedすると、舞台裏で何が起こっているのか、その取り組みをどのように指示するかについての理解が深まります。
この場合、入力のsed2番目のオカレンスが見つかるまでスタック入力を監視\n#.*\ndotanし、それが前の出力を一度に1行ずつ出力し始めるまで監視できます。それはちょっとクールです。私はこれについて多くのことを学びました。