Мне нужно разобрать файл, своего рода файл конфигурации, который принимает действительно простую грамматику: есть 2 вида многострочных блоков и тегов инлайн-разметки.
блок типа 1 обозначен open_tag и closing_tag плюс имя блока, пример
START_BLOCK_1 name
< content >
END_BLOCK_1
блоки типа 1 содержат только блоки типа 2, они в основном используются для включения или выключения блоков этого конфигурационного файла.
блок типа 2 помечается тегом в начале новой строки ( плюс имя ) и есть не закрывающий тег, закрытие неявно происходит, когда начинается новый блок или когда заканчивается файл, сам блок может содержать пустые строки.
START_BLOCK_2 name_1
< content >
< content >
< content >
START_BLOCK_2 name_2
< content >
< content >
< content >
START_BLOCK_2 name_3
< content >
< content >
последний вид маркера - это просто встроенный тег, специальное слово, которое присутствует в начале строки, и я просто хочу узнать, какое значение обозначено этим тегом
START_BLOCK_2 name_1
tag_1 red
tag_2 Jon
START_BLOCK_2 name_2
tag_1 blue
tag_2 Phil
Хороший последний пример может быть
START_BLOCK_2 name_1
< content >
START_BLOCK_2 name_2
< content >
START_BLOCK_1 name_1
START_BLOCK_2 name_3
< content >
START_BLOCK_2 name_4
< content >
END_BLOCK_1
START_BLOCK_2 name_5
< content >
Рассматривая имена блоков типа 2, мне нужно знать значения, связанные с каждым тегом (если они содержат теги, которые установлены) и если они являются частью блоков типа 1, и в этом случае атрибут имени блока типа 1, который их содержит.
Результат может быть сохранен в файл или распечатан, до тех пор, пока я могу разобрать это, я всегда могу перечитать вывод позже в отформатированном виде.
Разобрать этот файл относительно просто, но я никогда не делал этого с помощью оболочки GNU/linux, и я хотел бы знать, возможно ли это, и названия инструментов, созданных для этого.
EDIT
input
START_BLOCK_2 opt1
color red
START_BLOCK_1 opt2
START_BLOCK_2 opt3
name Jon
START_BLOCK_2 opt4
color blu
END_BLOCK_1
expected output
opt1 red
opt3 opt2
opt3 Jon
opt4 opt2
opt4 blu
Вот решение awk
при условии, что вам не нужны пустые строки в выводе примера.
awk '/START_BLOCK_1/ { block1=$2; next; } \
/END_BLOCK_1/ {block1=""; next; } \
/START_BLOCK_2/ { block2=$2; next; } \
/./ { if(block1) {print block2 " " block1} if(block2) { print block2 " " $2}
}' inp
он работает, сопоставляя каждую строку для начального или конечного блока. Если мы находимся «в» BLOCK_1, у нас будет имя, установленное в переменной block1
. Если мы «находимся» в BLOCK_2, это имя будет установлено в переменной block2
. В любой строке, которая не определяет блок и не является пустой (соответствует как минимум 1 символу), мы затем распечатываем материал на основе блоков, в которых мы находимся.