Фильтрация содержимого файла YAML с помощью sed / awk

Если ваши слова разделены пробелами, то awk может быть проще:

awk 'NF > 1 {a = $1; $1 = $2; $2 = a};1' <file
2
21.05.2019, 21:36
4 ответа

Решение 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

4
27.01.2020, 21:52

Вы можете сделать (на Mac):

tr "\n" "\t" < hosts.yml | sed $'s%\t\\[%\\\n\[%g' | grep 'prod\|dev' | sed $'s%.*\]\\\t%%g' | tr "\t" "\n"
  1. trвыведет все в одну строку
  2. Первый sedбудет линия разрыва перед каждым разделом
  3. grepвырежет линии (секции )нужные вам
  4. Второй sedудалит часть [].
  5. Последнее trразбивает строку, поэтому вы получаете одно имя хоста в строке.
2
27.01.2020, 21:52
awk 'BEGIN{RS="[";FS="]\n"} 
     $1 ~/(prod|dev)_env/ {print $2}' ex1
2
27.01.2020, 21:52

Это можно сделать с помощью GNU sed, как показано:

$ sed -nEe '
   /\[/!{H;$!d;}
   x;1!s/^\[(prod|dev)_env]\n//p
' hosts.yml
0
27.01.2020, 21:52

Теги

Похожие вопросы