Если ваши слова разделены пробелами, то awk
может быть проще:
awk 'NF > 1 {a = $1; $1 = $2; $2 = a};1' <file
Решение sed
:
sed -nEe '/\[(prod|dev)_env]/!d;N;:loop' -e 's/.*\n//;${p;d;};N;P;/\n\[/D;bloop' hosts.yml
/\[(prod|dev)_env]/!d
отбрасывает все строки до тех пор, пока [prod_env]
или [dev_env]
не будут найдены N;:loop
добавляет следующую строку и запускает цикл s/.*\n//
, потому что это либо строка [...env]
, либо мы уже напечатали ее в последнем цикле цикла ${p;d;}
печатает оставшиеся строки, если мы достигли последней строки при печати N;P
добавляет следующую строку и печатает текущую /\n\[/D
проверяет, начинается ли следующая строка с [
. В этом случае первая строка в буфере (, уже напечатанная ), может быть отброшена, и мы начнем с этой строки [
bloop
иначе петля Вместо того, чтобы добавлять в буфер следующую строку, печатать и удалять старую, можно пройти построчно, но для этого потребуется еще один цикл, потому что нельзя начать заново сD
Вы можете сделать (на Mac):
tr "\n" "\t" < hosts.yml | sed $'s%\t\\[%\\\n\[%g' | grep 'prod\|dev' | sed $'s%.*\]\\\t%%g' | tr "\t" "\n"
tr
выведет все в одну строку sed
будет линия разрыва перед каждым разделом grep
вырежет линии (секции )нужные вам sed
удалит часть []. tr
разбивает строку, поэтому вы получаете одно имя хоста в строке. Это можно сделать с помощью GNU sed
, как показано:
$ sed -nEe '
/\[/!{H;$!d;}
x;1!s/^\[(prod|dev)_env]\n//p
' hosts.yml