grep блок строк в переменную оболочки на основе шаблона соответствия

grep блок строк в переменную оболочки на основе шаблона соответствия

06.12.2019 09:07:10 Просмотров 31 Источник

Я ищу способ grep блока линий между {} на основе заданного шаблона.Я пробовал различные шаблоны, которые я нашел в google, но ни один из них не помогает моему делу.я не профессионал в регулярных выражениях.ищу какую-нибудь помощь для решения этой проблемы. Это пример исходного файла:

Data {
        status 400;
        server_name test.dummy.com;

        location /test {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_read_timeout 5m;
proxy_send_timeout 5m;
proxy_pass http://xyz.9201.com;

               proxy_http_version 1.1;
               proxy_set_header Upgrade $http_upgrade;
               proxy_set_header Connection "upgrade";
        }

        location /dev {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_read_timeout 5m;
proxy_send_timeout 5m;
proxy_pass http://xyz.9202.com;

               proxy_http_version 1.1;
               proxy_set_header Upgrade $http_upgrade;
               proxy_set_header Connection "upgrade";
        }

        location /prd {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_read_timeout 5m;
proxy_send_timeout 5m;
proxy_pass http://xyz.9203.com;

               proxy_http_version 1.1;
               proxy_set_header Upgrade $http_upgrade;
               proxy_set_header Connection "upgrade";
        }
}

если аргумент , передаваемый скрипту, является "dev", то он должен соответствовать шаблону location /dev и извлекать блок ниже в переменную оболочки:

местоположение / dev {

proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_read_timeout 5m;
proxy_send_timeout 5m;
proxy_pass http://xyz.9202.com;
               proxy_http_version 1.1;
               proxy_set_header Upgrade $http_upgrade;
               proxy_set_header Connection "upgrade";

я пробовал различные шаблоны команд sed/awk, но этот ниже дает мне какой-то ближайший результат.

awk '/dev/{print}' RS={ FS=} test.conf

результат:

$ awk '/dev/{print}' RS={ FS=} test.txt

proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_read_timeout 5m;
proxy_send_timeout 5m;
proxy_pass http://xyz.9201.com;

               proxy_http_version 1.1;
               proxy_set_header Upgrade $http_upgrade;
               proxy_set_header Connection "upgrade";
        }

        location /dev
У вопроса есть решение - Посмотреть?

https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern#comment104652191_59218263
Поэтому мы призываем людей добавить свои усилия, которые они приложили, чтобы решить свои собственные проблемы, не могли бы вы добавить то же самое в свой вопрос и сообщить нам об этом.

Ответы - grep блок строк в переменную оболочки на основе шаблона соответствия / grep a block of lines into a shell variable based on matching pattern

Austin Adams

06.12.2019 09:33:23

Я не уверен, что вы можете выполнить то, что вы хотите, используя grep сам по себе, но вы можете использовать команды sedи grepвместе, чтобы получить желаемый результат.

sed -n '/dev {/,/}/p' src_file

даст вам следующий результат:

location /dev {
  proxy_set_header X-Forwarded-Host $host;
  proxy_set_header X-Forwarded-Server $host;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header Host $http_host;
  proxy_read_timeout 5m;
  proxy_send_timeout 5m;
  proxy_pass http://xyz.9202.com;

           proxy_http_version 1.1;
           proxy_set_header Upgrade $http_upgrade;
           proxy_set_header Connection "upgrade";
  }

И если вы хотите удалить dev {and }, вы можете объединить команду sed с командой grep-v следующим образом:

sed -n '/dev {/,/}/p' src_file | grep -v "}" | grep -v "{"

что даст вам желаемый результат:

proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_read_timeout 5m;
proxy_send_timeout 5m;
proxy_pass http://xyz.9202.com;
           proxy_http_version 1.1;
           proxy_set_header Upgrade $http_upgrade;
           proxy_set_header Connection "upgrade";
https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern/59218549#comment104652791_59218549
FWIW, вы можете объединить два greps в один grep -v '[{}]'.
https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern/59218549#comment104652841_59218549
@RavinderSingh13: я отредактировал свой вопрос с помощью вещей, которые я пробовал.с самого утра я пробовал разные вещи. так как это один лайнер, я просто не добавил его к моему вопросу.мне все еще нужно решить главную логику, и то, что я попросил, было одной линейной моделью помощи. Там будут и люди не из unix, которые просто быстро придут, чтобы увидеть помощь этому великому порталу.
https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern/59218549#comment104652874_59218549
@Рамеш Чандер.metta, Спасибо за добавление усилий, неправильное или правильное не имеет значения, мы только поощряем людей добавлять свои усилия, я добавлю свою версию тоже сейчас:) ура.
Является ответом!
RavinderSingh13

06.12.2019 09:45:20

Мы могли бы сделать это в одном awkсебя, пожалуйста, попробуйте следовать.

awk '/}/ && found{exit} /location \/dev/{found=1;next} found && NF' Input_file

Так как ОП упомянул, что только 1-й набор должен быть напечатан, поэтому я использую exitздесь, чтобы выйти немедленно, как только кулак установил его напечатанным.

Пояснение: добавление пояснения к приведенному выше коду.

awk '                   ##Starting awk program from here.
/}/ && found{           ##Checking condition if a line contains } AND variable found is SET then do following.
  exit                  ##Exiting from program here.
}                       ##Closing BLOCK for above condition here.
/location \/dev/{       ##Checking condition here if a line contains location /dev then do following.
  found=1               ##Setting variable found to 1 here.   
  next                  ##next will skip all further statements from here.
}                       ##Closing BLOCK for above condition here.
found && NF             ##Checking condition is  found is SET and NF is NOT NULL then print current line.
' Input_file            ##Mentioning Input_file name here.

Выход будет следующим.

proxy_set_header X-Forwarded-Host ;
proxy_set_header X-Forwarded-Server ;
proxy_set_header X-Forwarded-For ;
proxy_set_header Host ;
proxy_read_timeout 5m;
proxy_send_timeout 5m;
proxy_pass http://xyz.9202.com;
               proxy_http_version 1.1;
               proxy_set_header Upgrade ;
               proxy_set_header Connection "upgrade";
https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern/59218685#comment104653075_59218685
это работает. но это не совсем соответствует шаблону (я согласен, что должен был быть более конкретным). если я добавлю еще одну строфу в файл с /dev2. это дает два результата.
https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern/59218685#comment104653122_59218685
@Рамеш Чандер.Метта, после того, как первая строфа напечатана, я просто выхожу из программы, которая будет очень быстрой и сэкономит ваше время.
https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern/59218685#comment104653393_59218685
Очень хорошо объяснил awk ++
https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern/59218685#comment104817953_59218685
@RavinderSingh13 что я могу изменить здесь, чтобы искать: location /AuditManagement/ {
https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern/59218685#comment104818507_59218685
@Рамеш Чандер.Метта, конечно, изменения /location \/dev/ с /location \/AuditManagement\/ {/ и она должна лететь дальше.
https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern/59218685#comment104818782_59218685
я попробовал ниже: Я заменил " на ", Потому что я должен использовать переменную вместо строки жесткого кода "AuditManagement". output=$(awk "/} / & & found{exit} /location \ / AuditManagement\ / {/{found=1; next} found && NF "" $CONF_FILE")
https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern/59218685#comment104819227_59218685
@Рамеш Чандер.Метта, нет в awkвы должны использовать только awk '...''цитата. Чтобы использовать переменные оболочки в awk, попробуйте что-то вроде awk -v var="$SHELL_VARIABLE" ваш код awk здесь....."файл" и т. д
https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern/59218685#comment104821087_59218685
@RavinderSingh13: дай мне попробовать и вернуться.
Mark Reed

06.12.2019 09:48:08

Попытка проанализировать файлы на основе блоков с помощью линейных инструментов-рискованное предложение без каких-либо гарантий. Большинство решений потерпят неудачу, если есть еще {...insideблок, вложенный в блок внешнего location(путем остановки после первого insideвместо соответствующего). Это может не быть проблемой с вашим конкретным файлом, но это решение будет обрабатывать его правильно:

awk '(inside && /{/)  { inside++ };
     (inside && /}/)  { --inside; if (!inside) { exit } };
     (inside) {print};
     /location \/dev[ \/{]/ { inside=1; }' src_file

Однако есть еще много способов сломать это. Реальная библиотека синтаксического анализатора, предназначенная для (или настраиваемая для) рассматриваемого синтаксиса, даст вам более надежные результаты, если это будет больше, чем одноразовая работа.

Пояснение: в конструкции этой программы используется переменная состояния, называемая inside, которая, если она ненулевая, означает, что текущая обрабатываемая строка находится внутри строфы. Каждая новая открытая скобка {вызывает увеличение значения, в то время как каждая закрытая скобка insideвызывает его уменьшение. Поэтому, как только он достигает нуля после того, как он был ненулевым, мы знаем, что мы закончили с целевой строфой и можем выйти.

Строфы обрабатываются по порядку, так что этот порядок очень важен. Самая последняя строфа ищет начальную locationстрока местоположения сама была бы напечатана последующими строфами. Но как бы то ни было, печать не вступает в силу до следующей строки файла.

Итак: если мы находимся внутри строфы и видим другую {, приращение {. если мы находимся внутри строфы и видим аinside, декремент {. Если сейчас ноль, значит, мы закончили, так что выходите. Если мы находимся внутри (независимо от того, видели ли мы только что { или}, пока мы не вышли), то выведите текущую строку. Если мы видим inside... затем следует либо пробел, либо косая черта, либо фигурная скобка, поэтому другое расположение, которое только начинается с location /dev, не будет соответствовать ... установите {значение 1, указывающее, что мы должны начать печать со следующей строки.

Обратите внимание, что в написанном виде программа предполагает, что начало {для всей строфы находится в той же строке, что и сама директива location. Если скобка находится на следующей строке, логика вложенности будет означать, что он будет печатать весь файл с этой точки. Это всего лишь пример хрупкости такого подхода.

https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern/59218718#comment104653183_59218718
мне нравится этот, так как у меня есть более сложные подразделы со многими фигурными скобками. это работает, но если у меня есть еще одна строфа с /dev2, ее отображение в другом разделе тоже.
https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern/59218718#comment104653505_59218718
Обновлено, чтобы быть более конкретным.
https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern/59218718#comment104818035_59218718
Привет.я пытаюсь настроить приведенное выше заявление awk, чтобы искать ниже: location /AuditManagement/ { . задохнется ли вышеизложенное, если есть / характер ? я не вижу никакого результата. никакая ошибка
https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern/59218718#comment104819257_59218718
Параметр /завершает соответствие регулярного выражения, если перед ним не поставить символ\, как в Примере. Символы между [...] несколько вариантов, так что приведенный выше код соответствует "расположение /Dev" с пробелом после /Дев, "место на /dev/" Слэш, или "расположение устройства /dev{" с фигурной скобкой. Поэтому, если вы замените devна AuditManagementи оставите все остальное таким же, что должно соответствовать вашим требованиям.
https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern/59218718#comment104821069_59218718
я думал так, как вы объяснили для [..] . но это не работает или, может быть, я делаю какую-то ошибку. у меня есть два / аудита и / AuditManagement/. скрипт способен найти /Audit, но не /AuditManagement/.
https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern/59218718#comment104822069_59218718
кажется, это не работает с моей стороны. я получил ответ на проверку. он пуст, когда я использую AuditManagement. это строка в исходном файле: location /AuditManagement/ {
https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern/59218718#comment104824975_59218718
Тогда /location \/AuditManagement[ \/{]/должен соответствовать ему.
https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern/59218718#comment104825137_59218718
Это возвращение пустым. [user@xxxxx test]$ awk '(inside && /{/) { inside++ }; (inside && /}/) { --inside; if (!inside) { exit } }; (inside) {print}; /location \/AuditManagement[ \/{]/ { inside=1; }' mi.conf
https://stackoverflow.com/questions/59218263/grep-a-block-of-lines-into-a-shell-variable-based-on-matching-pattern/59218718#comment104825544_59218718
Теперь это сработало. Я убрал дополнительное пространство между местоположением и / Auditmanagement. затем я получил результат обратно. Большое спасибо за помощь.
potong

08.12.2019 01:19:32

Это может сработать для вас (GNU sed):

sed -n '/^\s*location .*{$/h;/^\s*$\|[{}]/b;G;/location \/dev/P' file

Сделайте копию каждой строки, начинающейся location. Добавьте текущую копию к каждой строке и, если двойная строка содержит {, выведите только первую из них.

Пустые строки и строки, содержащие location /devи {, могут быть предварительно удалены.

Закрыть X