Вот еще один 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оператор выполнения lobal и ветвь создают 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
Есть только одно различие между этой командой и той, что выше, и это команда look вверху. Когда мы lООК в sed«s шаблона , как это работает , мы можем получить лучшее представление о том, что происходит за кулисами , и лучшее понимание того , как направить свои усилия.
В этом случае мы можем наблюдать за sedвводом в стек до тех пор, пока не обнаружим второе вхождение \n#.*\ndotanна входе, и когда он начнет печатать предыдущую строку за раз. Это круто. Я многому научился, работая над этим.