Комментировать все строки из последней прокомментированной строки в строке с 'foo'

Рассмотрим текстовый файл users.txt :

 #alice #bob charlie dotan eric 

Мне нужно прокомментировать все ( dotan ) последнюю прокомментированную строку до (включительно) dotan . Это результат:

 #alice #bob #charlie #dotan eric 

Есть ли хороший sed oneliner, чтобы сделать это? Я буду рад любому инструменту, а не просто sed .

В настоящее время я получаю номер строки последней прокомментированной строки:

 $ cat -n users.txt | grep '#' | tail -n1 2 #bob 

Затем я добавляю один и комментирую с sed :

 $ sed -i'' '3,/dotan/ s/^/#/' users.txt 

Я знаю, что могу быть умным, и все это вместе с некоторыми bc в уродливый однострочный. Неужели должен быть более чистый путь?

  • sed изменить формат строки журнала DNS
  • Как избежать одиночной цитаты?
  • обратные ссылки в regex `rename`
  • Как заменить начальный ноль пробелом в SED?
  • Передача переменной sed
  • Используйте sed, чтобы найти и заменить строку в нескольких файлах
  • Добавьте двойную кавычку, если между словами в столбце есть пробел
  • Как прокомментировать строку на основе слова, с которого оно начинается?
  • 4 Solutions collect form web for “Комментировать все строки из последней прокомментированной строки в строке с 'foo'”

    Как насчет

     perl -pe '$n=1 if s/^dotan/#$&/; s/^[^#]/#$&/ unless $n==1;' file 

    или, та же самая идея в awk:

     awk '(/^dotan/){a=1; sub(/^/,"#",$1)} (a!=1 && $1!~/^#/){sub(/^/,"#",$1);}1; ' file 

    Если существующие прокомментированные строки образуют единый непрерывный блок, тогда вы можете сопоставлять только с первой прокомментированной строкой, комментируя только те строки до и включая ваш шаблон конца, которые еще не прокомментированы

     sed '/^#/,/dotan/ s/^[^#]/#&/' file 

    Если существующие комментарии не смежны, то из-за жадного характера совпадения совпадений я думаю, что вам нужно будет сделать что-то вроде

     tac file | sed '/dotan/,/^#/ s/^[^#]/#&/' | tac 

    т.е. совпадение вверх от шаблона конца к «первому» комментарию – очевидно, это не так удобно, если вы хотите получить решение на месте.

    Вы можете обрабатывать оба случая (прокомментированные строки в одном непрерывном блоке или вкрапленные среди несвязанных строк) с помощью одного вызова sed :

     sed '1,/PATTERN/{/^#/{x;1d;b};//!{H;/PATTERN/!{1h;d};//{x;s/\n/&#/g}}}' infile 

    Это обрабатывает только строки в диапазоне 1,/PATTERN/ . Оно меняет пространство пробела w. пространство шаблонов каждый раз, когда строка комментируется (поэтому в буфере удержания не более одной прокомментированной строки) и добавляет каждую строку, которая не комментируется в старом пространстве H (когда в первой строке, 1d и соответственно 1h также необходимы удалить начальную пустую строку в буфере удержания).
    Когда он достигает строки, соответствующей PATTERN, она также добавляет ее в старый буфер H , e x изменяет буферы и затем заменяет каждый символ \n ewline в пространстве шаблонов на \n ewline и # (то есть все строки в пространство шаблонов теперь начинается с # , включая первую строку, поскольку первая строка в пространстве удержания всегда представляет собой прокомментированную строку).
    С образцом infile :

     alice #bob bill #charlie ding dong dotan jimmy #garry 

    Бег:

     sed '1,/dotan/{ # if line is in this range -start c1 /^#/{ # if line is commented -start c2 x # exchage hold space w. pattern space 1d # if 1st line, delete pattern space b # branch to end of script } # -end c2 //!{ # if line is not commented -start c3 H # append to hold space /dotan/!{ # if line doesn't match dotan -start c4 1h # if 1st line, overwrite hold space d # delete pattern space } # -end c4 //{ # if line matches dotan -start c5 x # exchage hold space w. pattern space s/\n/&#/g # add # after each newline character } # -end c5 } # -end c3 }' infile # -end c1 

    выходы:

     alice #bob bill #charlie #ding #dong #dotan jimmy #garry 

    поэтому он комментирует только строки из (и исключая) #charlie до (и в том числе) dotan и оставляя другие строки нетронутыми.
    Конечно, это предполагает, что всегда существует как минимум одна прокомментированная строка перед строкой, соответствующей PATTERN . Если это не так, вы можете добавить дополнительную проверку перед заменой: /^#/{s/\n/&#/g}

    Вот еще одно 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 распространяет свои буферы между каждой последней прокомментированной строкой в ​​любой серии, никогда не сохраняя еще одного в своем буфере, чем необходимо для точного отслеживания последнего прокомментированного вхождения, и если в любое время он встречает последнюю строку, делая это, он попытается заключительный оператор выполнения и ветвь t чтобы весь буфер был напечатан, иначе он будет записывать все те строки, которые он освобождает из своего буфера, как только это произойдет.

    Наверное, это то, что заставило аккордеоны вспомнить …

     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 

    Между этой командой и одним выше есть только одно отличие, и это команда l ook наверху. Когда мы работаем над sed пространством sed мы можем лучше понять, что происходит за кулисами, и лучше понять, как направить свои усилия.

    В этом случае мы можем наблюдать ввод sed stack до тех пор, пока не найдем второе вхождение \n#.*\ndotan на входе и что когда он начнет печатать предыдущую строку за раз. Это здорово. Я многому научился над этим.

    Interesting Posts

    Вино: загрузите старое программное обеспечение Access – неверный заголовок ELF

    Скрипт для автоматического запуска программ после перезапуска

    Я хочу отредактировать текст определенного файла

    Прерывая rsync с помощью ctrl-c, следует ли использовать `–partial` или` –append`?

    Как grub2 загружает ядро ​​из тома LVM?

    Какие значения return / exit можно использовать в bash-функциях / скриптах?

    Невозможно установить Linux Mint Cinnamon или Ubuntu, в то время как переключаемая графика включена

    Как предоставить права пользователя root?

    Base64 декодирует и перезаписывает файл

    Проверка наличия файлов в некоторых удаленных папках с помощью bash

    Как запустить ядро ​​linux usermode?

    Как перечислить доступные алгоритмы ключа хоста для клиента SSH?

    Будет ли иметь десятки неактивных логинов ухудшить производительность

    Как перенести настройки брандмауэра с одного веб-сервера Debian Squeeze на другой?

    Что использует память?

    Linux и Unix - лучшая ОС в мире.