【问题标题】:Powershell - F5 iRules -- Extracting iRulesPowershell - F5 iRules -- 提取 iRules
【发布时间】:2020-09-01 02:46:45
【问题描述】:

我收到了一个 F5 负载均衡器的配置文件,并被要求使用 PowerShell 对其进行解析,以便它为找到的每个 iRule 创建一个 .txt 文件。我对解析很陌生,我似乎无法理解它。

我设法提取了每条规则的名称并创建了一个单独的 .txt 文件,但我无法将规则的内容写入其中。由于并非所有规则都相同,我似乎无法使用正则表达式。

从配置文件中提取:

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 脚本读出每条规则括号之间的内容? (在本例中为“某些内容”和“某些其他内容”)

【问题讨论】:

    标签: powershell f5


    【解决方案1】:

    通常解析涉及将特定输入(“字符串”)转换为 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 }
    

    【讨论】:

    • 有没有办法在另一个循环的开始处定义循环的结束? (当找到另一个 ltm 规则时)因为一些 ltm 规则在其中具有函数,也带有大括号。不想过早停止循环。
    • 查看帖子中的最新编辑。它会在整个字符串中为您提供大括号之间的所有内容。
    【解决方案2】:

    要解析具有灵活结构的数据,可以使用状态机。也就是逐行读取数据,保存你所处的状态。这是规则的开始吗?实际规则?统治结束?通过了解当前状态,可以对数据执行操作。像这样,

    # 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
    }
    

    【讨论】:

    • 有没有办法在另一个循环的开始处定义循环的结束? (当找到另一个 ltm 规则时)因为一些 ltm 规则在其中具有函数,也带有大括号。不想过早停止循环。
    猜你喜欢
    • 1970-01-01
    • 2021-06-06
    • 2011-12-03
    • 2020-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-10
    • 1970-01-01
    相关资源
    最近更新 更多