Блок печати AWK, который НЕ содержит определенного текста

У меня есть следующий файл данных:

variable "ARM_CLIENT_ID" {
  description = "Client ID for Service Principal"
}

variable "ARM_CLIENT_SECRET" {
  description = "Client Secret for Service Principal"
}

# [.....loads of code]

variable "logging_settings" {
  description = "Logging settings from TFVARs"
}

variable "azure_firewall_nat_rule_collections" {
  default = {}
}

variable "azure_firewall_network_rule_collections" {
  default = {}
}

variable "azure_firewall_application_rule_collections" {
  default = {}
}

variable "build_route_tables" {
  description = "List of Route Table keys that need direct internet prior to Egress FW build"
  default = [
    "shared_services",
    "sub_to_afw"
  ]
}

Есть 2 вещи, которые я хочу сделать:

  • вывести имена переменных без кавычек
  • ТОЛЬКО печатайте имена переменных, если блок кода НЕ содержит default

Я знаю, что могу напечатать имена переменных так: awk '{ gsub("\"", "") }; (/variable/ && $2 !~ /^ARM_/) { print $2}'

Я знаю, что могу распечатать блоки кода с помощью: awk '/variable/,/^}/', что приводит к:

# [.....loads of code output before this]

variable "logging_settings" {
  description = "Logging settings from TFVARs"
}
variable "azure_firewall_nat_rule_collections" {
  default = {}
}
variable "azure_firewall_network_rule_collections" {
  default = {}
}
variable "azure_firewall_application_rule_collections" {
  default = {}
}
variable "build_route_tables" {
  description = "List of Route Table keys that need direct internet prior to Egress FW build"
  default = [
    "shared_services",
    "sub_to_afw"
  ]
}

Однако я не могу понять, как печатать блоки кода, «если» они не содержат default. Я знаю, что мне нужно будет использовать оператор if и, возможно, некоторые переменные, но я не уверен, как это сделать.

Этот блок кода НЕ должен появляться в выводе, для которого я беру имя переменной:

variable "build_route_tables" {
  description = "List of Route Table keys that need direct internet prior to Egress FW build"
  default = [
    "shared_services",
    "sub_to_afw"
  ]
}

Конечный вывод НЕ должен содержать те, которые имели default:

# [.....loads of code output before this]
expressroute_settings
firewall_settings
global_settings
peering_settings
vnet_transit_object
vnet_shared_services_object
route_tables
logging_settings

Предпочтительно, чтобы это была одна команда или файл AWK, без конвейера. У меня есть применения для этого, которые предпочитают отсутствие трубопровода.

Обновлено: обновить идеальные результаты (пропущены некоторые примеры с default)

Почему azure_firewall_application_rule_collections в выводе? Блок кода имеет default = {}

Barmar 11.12.2020 21:54

Условие !/regexp/ будет истинным, если запись не соответствует регулярному выражению.

Barmar 11.12.2020 21:55

@Бармар; Хорошо, как я могу использовать это, чтобы удалить блок, который мне не нужен?

Beefcake 11.12.2020 22:08

Если вы напечатаете только те блоки, которые удовлетворяют этому условию, вы исключите остальные блоки.

Barmar 11.12.2020 22:16

пожалуйста, обновите ожидаемый результат, чтобы он соответствовал образцу ввода (например, expressroute_settings не находится в образце ввода, но находится в ожидаемом выводе... ??

markp-fuso 11.12.2020 22:22

Нет @markp-fuso, это не так, но, как вы можете видеть в верхней части этого списка, я сделал комментарий, что он включает в себя много вывода кода перед ним. в основном, я обрезал кучу бесполезного текста

Beefcake 11.12.2020 22:24

@Бармар; именно это я и спрашиваю. Как мне напечатать только те блоки, которые НЕ включают в себя default? Не имею представления.

Beefcake 11.12.2020 22:24

По умолчанию ничего не печатается. Поэтому, если вы используете !/default =/ в качестве условия, он будет печатать только эти блоки.

Barmar 11.12.2020 22:25

@Бармар; не могли бы вы написать команду/формулу, чтобы я мог полностью понять, как вы хотите, чтобы это было

Beefcake 11.12.2020 22:27
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
9
644
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Используя GNU awk:

awk -v RS = "}" '/variable/ && !/default/ && !/ARN/ { var=gensub(/(^.*variable ")(.*)(".*{.*)/,"\\2",$0);print var }' file

Установите разделитель записей на «}», а затем проверьте записи, которые содержат «переменная», не содержат значения по умолчанию и не содержат «ARM». Используйте gensub, чтобы разделить строку на три части на основе регулярных выражений и установить переменную var во вторую часть. Распечатайте переменную var.

Выход:

logging_settings

Последние 3 строки не должны быть в выводе, так как у них есть default.

Barmar 11.12.2020 22:29

Я не думаю, что ему нужны записи ARM, так что это просто logging_settings

Raman Sailopal 11.12.2020 22:31
$ awk -v RS= '!/default =/{gsub(/"/,"",$2); print $2}' file

ARM_CLIENT_ID
ARM_CLIENT_SECRET
[.....loads
logging_settings

конечно, вывод не соответствует вашему, поскольку он несовместим с входными данными.

Ответ принят как подходящий

Предположения и сборник заметок из вопроса и комментариев ОП:

  • все блоки определения переменных заканчиваются правой фигурной скобкой (}) в первом столбце новой строки
  • мы отображаем только variable имена (без двойных кавычек)
  • мы не отображаем имена variable, если тело определения переменной содержит строку default
  • мы не отображаем имя variable, если оно начинается со строки ARM_

Одно (несколько подробное) awk решение:

ПРИМЕЧАНИЕ. Я скопировал входные данные образца в свой локальный файл variables.dat

awk -F'"' '                                              # use double quotes as the input field separator
/^variable / && $2 !~ "^ARM_"  { varname = $2            # if line starts with "^variable ", and field #2 is not like "^ARM_", save field #2 for later display
                                 printme = 1             # enable our print flag
                               }
/variable/,/^}/                { if ( $0 ~ "default" )   # within the range of a variable definition, if we find the string "default" ...
                                    printme = 0          # disable the print flag
                                 next                    # skip to next line
                               }
printme                        { print varname           # if the print flag is enabled then print the variable name and then ...
                                 printme = 0             # disable the print flag
                               }
' variables.dat

Это генерирует:

logging_settings

забыл сказать "спасибо" прошлой ночью, это очень помогло и дало мне больше информации о функциональности awk

Beefcake 12.12.2020 11:00

Другой вариант awk с использованием переменной skip для управления индексом массива, содержащим имена переменных:

awk '
    /^[[:blank:]]*#/ { next }
    $1= = "variable"   { gsub(/["]/,"",$2); vars[skip?n:++n]=$2; skip=0 } 
    $1= = "default"    { skip=1 }
    END { if (skip) n--; for(i=1; i<=n; i++) print vars[i] }
' code

Первое правило просто пропускает строки комментариев. Если вы хотите пропустить "ARM_" переменные, вы можете добавить тест на $2.

Пример использования/вывода

В вашем примере кода в code все переменные без default:

$ awk '
>     /^[[:blank:]]*#/ { next }
>     $1= = "variable"   { gsub(/["]/,"",$2); vars[skip?n:++n]=$2; skip=0 }
>     $1= = "default"    { skip=1 }
>     END { if (skip) n--; for(i=1; i<=n; i++) print vars[i] }
> ' code
ARM_CLIENT_ID
ARM_CLIENT_SECRET
logging_settings

Вот еще одно, возможно, более короткое решение.

$ awk -F'"' '/^variable/&&$2!~/^ARM_/{v=$2} /default =/{v=0} /}/&&v{print v; v=0}' file
logging_settings

Другие вопросы по теме