Разделитель, который может / не может занимать несколько строк, используя sed - PullRequest
0 голосов
/ 23 мая 2018

У меня есть предварительно сгенерированные файлы конфигурации из утилиты.Как извлечь строку параметра, которая ограничена '),, которая может занимать или не охватывать несколько строк?

FILE1 может выглядеть так - PARM3 охватывает несколько строк:

OPERAND      ID          = 'XXXX',
             ....
             PARM3       = ( 'VALUE3A',
                              ....
                             'VALUE3n'),
             PARM4       = ( 'VALUE4',
                              ....
                             'VALUE4n'),
                              ....

или FILE2 может выглядеть следующим образом - PARM3 не занимает несколько строк:

OPERAND      ID          = 'XXXX',
             ....
             PARM3       = ( 'VALUE3A'),
             PARM4       = ( 'VALUE4',
                              ....
                              'VALUE4n'),
             ....

Для FILE1 извлечение хорошо , если разделитель '), находится в другой строке:

sed -n "/.* PARM3 .*/,/')\,/p" FILE1

Вывод:

  PARM3       = ( 'VALUE3A',
                  ....
                  'VALUE3n'),

Для FILE2 извлечение не выполняетсяработать , если разделитель '), находится на одной строке:

sed -n "/.* PARM3 .*/,/')\,/p" FILE2

Вывод:

        PARM3       = ( 'VALUE3A'),
        PARM4       = ( 'VALUE4',
                         ....
                        'VALUE4n'),

Как я могу исправить это выражение sed, используя sed только для обработки разделителякоторые могут или не могут быть на одной линии?

Ответы [ 3 ]

0 голосов
/ 23 мая 2018

[РЕДАКТИРОВАТЬ] более просто:

sed -n '/PARM3/,/)/{p;/)/q}' file

путь с помощью sed:

sed -n '/PARM3/{:a;/)/{p;q};N;ba}' file

детали:

/PARM3/ {     # if PARM3 is found
    :a            # define a label "a"
    /)/ {         # if ) is found
        p             # print the pattern space
        q             # quit
    }
    N             # append the next line to the pattern space
    ba            # go to label a
}
0 голосов
/ 23 мая 2018

Вы можете использовать эту команду gnu-awk, которая использует пользовательский RS:

awk -v RS='[[:blank:]]*PARM3[[:blank:]]*=[[:blank:]]*\\([^)]*\\),[[:blank:]]*' 'RT{print RT}' file

Для файла1 это дает:

     PARM3       = ( 'VALUE3A',
                      ....
                     'VALUE3n'),

Для файла2 это дает:

    PARM3       = ( 'VALUE3A'),
0 голосов
/ 23 мая 2018

Если у вас есть GNU grep, вы можете использовать опцию -z для обработки всего ввода в виде одной строки:

$ grep -Ezo '\s+PARM3\s+=\s+\([^)]*\)' FILE2

             PARM3       = ( 'VALUE3A',
                              ....
                             'VALUE3n')

-o не сохраняет ничего, кроме соответствия, а -E включаетрасширенные регулярные выражения.

Регулярное выражение ищет PARM3 =, окруженное произвольным числом пробелов, за которым следует (, а затем все до и включая закрывающий ).Чтобы избежать жадного сопоставления, я использую [^)] («не закрывающая скобка»).

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

$ grep -Ezo 'PARM3\s+=\s+\([^)]*\),?' infile
PARM3       = ( 'VALUE3A',
                              ....
                             'VALUE3n'),

или для получения правильного выравнивания, но не новой строки, предшествующей совпадению:

$ grep -Ezo '[[:blank:]]*PARM3\s+=\s+\([^)]*\),?' infile
             PARM3       = ( 'VALUE3A',
                              ....
                             'VALUE3n'),
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...