Powershell — F5 iRules Извлечение iRules

Я получил файл конфигурации балансировщика нагрузки F5, и меня попросили проанализировать его с помощью PowerShell, чтобы он создавал файл .txt для каждого найденного iRule. Я очень новичок в синтаксическом анализе, и я не могу обдумать это.

Мне удалось извлечь имя каждого правила и создать отдельный файл .txt, но я не могу записать в него содержимое правила. Поскольку не все правила идентичны, я не могу использовать Regex.

Выдержка из файла конфигурации:

ltm rule /Common/irule_name1 {
SOME CONTENT
}

ltm rule /Common/irule_name2 {
SOME OTHER CONTENT
}

Что у меня есть на данный момент

$infile = "F5\config_F5"

$ruleslist = Get-Content $infile

foreach($cursor in $ruleslist)
{
if($cursor -like "*ltm rule /*") #new object started
{
    #reset all variables to be sure
    $content=""

    #get rulenames
    $rulenameString = $cursor.SubString(17)
    $rulename = $rulenameString.Substring(0, $rulenameString.Length -2)
    $outfile = $rulename + ".irule"

    Write-Host $outfile
    Write-Host "END Rule"
    #$content | Out-File -FilePath "F5/irules/" + $outfile
}
}

Как я могу заставить свой скрипт powershell считывать то, что находится в скобках каждого правила? (В данном случае «НЕКОТОРОЕ СОДЕРЖИМОЕ» и «ДРУГОЕ СОДЕРЖИМОЕ»)


person Realmlist    schedule 15.05.2020    source источник


Ответы (2)


Как правило, синтаксический анализ включает преобразование определенного ввода («строки») в «объект», который PowerShell может понять (например, HTML, JSON, XML и т. д.), и пройти, «расставляя точки» по каждому объекту.

Если вы не можете преобразовать его в какие-либо известные форматы (я не знаком с конфигурационными файлами F5...), и вам нужно только узнать содержимое между фигурными скобками, вы можете использовать приведенный ниже код.

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

# You can Get-Content FileName as well.
$string = @'
ltm rule /Common/irule_name1 {
SOME CONTENT
}

ltm rule /Common/irule_name2 {
SOME OTHER CONTENT
}
'@

function fcn-get-content {
    Param (
        [ Parameter( Mandatory = $true ) ]
        $START,
        [ Parameter( Mandatory = $true ) ]
        $END,
        [ Parameter( Mandatory = $true ) ]
        $STRING
    )
    $found_content    = $string[ ( $START + 1 ) .. ( $END - 1 ) ]
    $complete_content = $found_content -join ""
    return $complete_content
}

for( $i = 0; $i -lt $string.Length; $i++ ) {
#   Find opening brace
    if( $string[ $i ] -eq '{' ) {
        $start = $i
    }
#   Find ending brace
    elseif( $string[ $i ] -eq '}' ) {
        $end = $i
        fcn-get-content -START $start -END $end -STRING $string
    }
}

Чтобы получить все, что заключено в фигурные скобки (даже вложенные скобки):

$string | Select-String '[^{\}]+(?=})' -AllMatches | % { $_.Matches } | % { $_.Value }
person Vish    schedule 15.05.2020
comment
Есть ли способ определить конец цикла в начале другого цикла? (Когда найдено другое правило ltm) Потому что в некоторых правилах ltm есть функции, также с фигурными скобками. Не хотелось бы останавливать цикл преждевременно. - person Realmlist; 15.05.2020
comment
Проверьте последнее редактирование в сообщении. Это даст вам все, что находится между фигурными скобками, по всей строке. - person Vish; 15.05.2020

Для анализа данных с гибкой структурой можно использовать конечный автомат. То есть читать данные построчно и сохранять то состояние, в котором вы находитесь. Это начало правила? Актуальное правило? Конец правления? Зная текущее состояние, можно выполнять действия с данными. Вот так,

# Sample data
$data = @()
$data += "ltm rule /Common/irule_name1 {"
$data += "SOME CONTENT"
$data += "}"
$data += "ltm rule /Common/irule_withLongName2 {"
$data += "SOME OTHER CONTENT"
$data += "SOME OTHER CONTENT2"
$data += "}"
$data += ""
$data += "ltm rule /Common/irule_name3 {"
$data += "SOME DIFFERENT CONTENT"
$data += "{"
$data += "WELL,"
$data += "THIS ESCALATED QUICKLY"
$data += "}"
$data += "}"

# enum is used for state tracking
enum rulestate {
start
stop
content
}

# hashtable for results
$ht = @{}

# counter for nested rules
$nestedItems = 0

# Loop through data
foreach($l in $data){

    # skip empty lines
    if([string]::isNullOrEmpty($l)){ continue }

    # Pick the right state and keep count of nested constructs
    if($l -match "^ltm rule (/.+)\{") {
        # Start new rule
        $state = [rulestate]::start
    } else {
        # Process rule contents

        if($l -match "^\s*\{") {
            # nested construct found
            $state = [rulestate]::content
            ++$nestedItems
        } elseif ($l -match "^\s*\}") {
            # closing bracket. Is it
            # a) closing nested
            if($nestedItems -gt 0) {
                $state = [rulestate]::content
                --$nestedItems
            } else {
                # b) closing rule
                $state = [rulestate]::stop
            }
        } else {
            # ordinary rule data
            $state = [rulestate]::content
        }
    }

    # Handle rule contents based on state
    switch($state){
        start {
            $currentRule = $matches[1].trim()
            $ruledata = @()
            break
        }
        content {
            $ruledata += $l
            break
        }
        stop {
            $ht.add($currentRule, $ruledata)
            break
        }
        default { write-host "oops! $state" }
    }

    write-host "$state => $l"
}

$ht

Правила вывода

SOME CONTENT

SOME OTHER CONTENT
SOME OTHER CONTENT2

SOME DIFFERENT CONTENT
{
WELL,
THIS ESCALATED QUICKLY
}
person vonPryz    schedule 15.05.2020
comment
Есть ли способ определить конец цикла в начале другого цикла? (Когда найдено другое правило ltm) Потому что в некоторых правилах ltm есть функции, также с фигурными скобками. Не хотелось бы останавливать цикл преждевременно. - person Realmlist; 15.05.2020