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

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

Мне нужно регулярное выражение для сбора записей регистрации хоста DHCP

Мне нужно проанализироватьdhcpd.confфайл, для всех резервирований хостов, и если возможно, захватить их в файл или массив Bash. Так что если резервирование хостов определено следующим образом,

    host Service-Ethernet {
        hardware ethernet 11:11:11:11:11:11;
        fixed-address 192.168.0.3;
        option host-name "service";
    }

    host Service-Wifi {
        hardware ethernet 22:22:22:22:22:22;
        fixed-address 192.168.0.4;
    }

    host Test {
        hardware ethernet 33:33:33:33:33:33;
        fixed-address 192.168.0.5
        option host-name "test";
    }

Вывод в файл или массив Bash...

11:11:11:11:11:11, 192.168.0.3, service
22:22:22:22:22:22. 192.168.0.4,
, 192.168.0.5, test

Если один из трех параметров отсутствует, оставьте его пустым.

Даже если выражение должно быть применено построчно, это все еще приемлемо. Я могу обернуть выражение через скрипт Bash, который читает файл конфигурации построчно, конечно.

решение1

parse_dhcp.awkС как

#!/usr/bin/env awk -f

function output() {
    printf "%s, %s, %s\n", hw, fa, opt
}

$1 == "host" {
    if (NR > 1) output()
    hw = fa = opt = ""
    next
}

{sub(/;$/, "")}
$1 == "hardware"      {hw = $NF}
$1 == "fixed-address" {fa = $NF}
$1 == "option"        {opt = $NF; gsub(/"/, "", opt)}

END {output()}

затем

awk -f parse_dhcp.awk dhcp.conf

Что еще более неясно, этот файл имеет допустимый синтаксис Tcl, поэтому нам просто нужно написать DSL, чтобы мы могли оценить файл как скрипт Tcl:

#!/usr/bin/env tclsh

proc host {name data} {
    global vars
    array set vars {hardware "" fixed-address "" option ""}
    eval $data
    puts "$vars(hardware), $vars(fixed-address), $vars(option)"
}

proc unknown {cmd args} {
    global vars
    set vars($cmd) [lindex $args end]
}

set file [lindex $argv 0]
source $file

и

tclsh parse_dhcp.tcl dhcp.conf

решение2

Следующий однострочный код Perl, кажется, выводит почти то, что вам нужно:

perl -ane 'print $F[-1] =~ s/[";]//gr unless /[{}]/; print /^$/ ? "\n" : " "'

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

perl -ane 'if (/host/ .. /}/) {
               print $F[-1] =~ s/[";]//gr unless /[{}]/;
               print /}/ ? "\n" : " "
           }'

что значит

  • если мы находимся между строками, содержащими hostи }, мы обрабатываем входные данные, в противном случае мы их пропускаем.
  • если текущая строка не содержит фигурных скобок, то печатаем последнее слово, удалив из него точки с запятой и двойные кавычки
  • если строка содержит закрывающуюся фигурную скобку, мы выводим новую строку, в противном случае — пробел.

решение3

Итак, я видел, как люди отвечали разными и креативными решениями. Как энтузиаст регулярных выражений, я старался отвечать регулярными выражениями по мере необходимости.

Оказывается, ваш образец не является правильно сформированным документом из-за отсутствия точки с запятой в операторе Host Test.

Видите ли, здесь есть синтаксическая ошибка, которая делает недействительными два совершенно разумных выражения внутри оператора host Test: fixed-address и option.

Если вы хотите работать с правильно сформированными документами, а этот пример оказался ошибкой, то вы можете использовать:

host\s+[\w\-]+\s*\{(\s+hardware\s+ethernet\s+(([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2});)?(\s*fixed-address\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3});)?(\s*option\s+host-name\s+"(.*?)";)?\s*\}

Тогда строка замены будет иметь вид:

\2, \5, \7

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

Вы можете проверить свои варианты вhttps://regex101.com/

Дайте мне знать, если я ошибся. Удачи.

Связанный контент