Как получить определенный шаблон перед матчем? - PullRequest
2 голосов
/ 18 октября 2019

В настоящее время я работаю с несколькими файлами конфигурации, которые используют следующий формат:

[Stanza1]
action.script=1
action.ping=0
action.lookup=1
action.notable.param=0
action.script.filename=script.pl
[Stanza2]
action.script=0
action.ping=0
action.lookup=1
[Stanza3]
action.script=1
action.ping=0
action.lookup=0
action.script.filename=script.pl

Я хочу знать, какие разделы включают "action.script.filename = script.pl", поэтому ожидаемый результатбыло бы

[Stanza1]
[Stanza3]

Использование чего-то вроде:

grep -B 10 "action.script.filename = script.pl" file

не работает в случаях, когда имя раздела превышает 10 строк перед совпадением, и оказывается довольно громоздким в использовании.

Есть предложения, как это сделать?

Ответы [ 5 ]

4 голосов
/ 18 октября 2019

Следующая команда sed поможет:

sed -n '/^\[/h;/^action\.script\.filename=script\.pl$/{x;p}'

Вы можете попробовать это здесь .

Когда встречается строка, начинающаяся с "[", он сохраняет его в своем буфере хранения. Когда он встречает строку «action.script.filename = script.pl», он печатает содержимое буфера хранения.

1 голос
/ 18 октября 2019

Эта строка кода работает для меня

grep '^\[Stanza\|^action.script.filename=script.pl$' fileName | grep -B1 'action.script.filename=script.pl' | grep -v 'action.script.filename=script.pl\|\-\-'

Объяснение:

grep '^\[Stanza\|^action.script.filename=script.pl$' fileName

соответствует либо [Stanza ] * строкам, либо action.script.filename = script.pl единиц. Вывод выглядит примерно так

[Stanza1]
action.script.filename=script.pl
[Stanza2]
[Stanza3]
action.script.filename=script.pl

Добавление этого фильтра | grep -B1 'action.script.filename=script.pl' приведет к этому

[Stanza1]
action.script.filename=script.pl
--
[Stanza3]
action.script.filename=script.pl

Теперь вам просто нужно очистить вывод от ненужных частей

| grep -v 'action.script.filename=script.pl\|\-\-'

Это окончательный вывод

[Stanza1]
[Stanza3]
1 голос
/ 18 октября 2019

С awk

$ awk '/action\.script\.filename=script\.pl/{print h} /^\[/{h=$0}' ip.txt
[Stanza1]
[Stanza3]
  • /^\[/ строк, начинающихся с символа [, вы также можете использовать что-то вроде /Stanza/, если оно однозначно определяет строки заголовка
    • h=$0 для таких строк, сохранить содержимое ($0) в переменную h
  • /action\.script\.filename=script\.pl/, если строка ввода соответствует заданным критериям поиска
    • print h выведите значение h variable
    • , если вы соответствуете целой строке, тогда вы также можете использовать строковое совпадение $0 == "action.script.filename=script.pl" вместо регулярного выражения
1 голос
/ 18 октября 2019

Я не уверен, что это можно сделать чисто с помощью grep. Я бы порекомендовал небольшой скрипт bash:

while read line
do
    if [[ $line =~ \[.* ]]; then
        # save stanza for later
        stanza=$line
    fi
    if [[ $line =~ action.script.filename=script.pl ]]; then
        echo $stanza
    fi
done < file
0 голосов
/ 18 октября 2019
    awk '/^\[.*\]$/{stanza=$0;next} /action.script.filename=script.pl/{print stanza}' filename
    [Stanza1]
    [Stanza3]

Вы можете сохранить каждый раздел в переменной с именем stanza и перейти к следующей строке. Всякий раз, когда вы видите строку action.script.filename=script.pl, выведите переменную stanza.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...