разбор действительно простой грамматики разметки с помощью shell-скрипта

Мне нужно разобрать файл, своего рода файл конфигурации, который принимает действительно простую грамматику: есть 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
0
18.11.2016, 20:20
1 ответ

Вот решение 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 символу), мы затем распечатываем материал на основе блоков, в которых мы находимся.

2
28.01.2020, 02:34

Теги

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