Regex Powershell-在内部分隔输出和操作数据

Regex Powershell-在内部分隔输出和操作数据,regex,powershell,Regex,Powershell,我正在尝试创建一个Powershell脚本,该脚本基于输入TXT或CSV,将其拆分为由特定正则表达式分隔的部分,然后根据其他正则表达式操作其中的数据 更具体地说,我正在尝试操作NAT规则库中的数据,其格式如下: IP version : IPv4 Index : 1 ----------General---------- Original Source : Any Translated Source : ORIGINAL

我正在尝试创建一个Powershell脚本,该脚本基于输入TXT或CSV,将其拆分为由特定正则表达式分隔的部分,然后根据其他正则表达式操作其中的数据

更具体地说,我正在尝试操作NAT规则库中的数据,其格式如下:

IP version            : IPv4
Index                 : 1
----------General----------
Original Source       : Any
Translated Source     : ORIGINAL
Original Destination  : 192.168.1.1
Translated Destination: ORIGINAL
Original Service      : IKE
Translated Service    : ORIGINAL
Inbound Interface     : Any
Outbound Interface    : Any
Comment               : IKE NAT
Enable NAT Policy     : True
System Policy         : True
----------Advanced----------
[...] (irrelevant data)
我试图实现的是获取所有数据并对其进行操作,以便创建一个命令,该命令将通过另一个防火墙上的API为TXT文件中存在的所有NAT规则自动添加该规则,因此在本例中:

add nat-rule position 1 enabled true original-source "Any" translated-source "Original" original-destination "192.168.1.1" translated-destination: "Original" original-service "IKE" translated-service: "Original" comment "IKE NAT"
此规则的位置应基于索引变量

我基本上一直在说程序:这些部分以“IP版本”开始,以“系统策略:…”结束

对于这些部分中的每一部分,我相信我可以将正则表达式分配给一个变量,如果它匹配,它会将值分配给一个新变量

如何使用Powershell实现这一点

到目前为止,我已成功生成以下脚本:

$filepath = 'C:\test.txt'
$getfile = Get-Content $filepath -Raw
$splitfile = $getfile - split 

foreach($object in $splitfile){
 Write-Host $object
}

提前感谢。

要解析这样的文件,确实需要进行一些拆分和替换

完成后,我认为使用cmdlet获取哈希表中的所有值并使用该哈希表中的值填充模板字符串以构建命令字符串是最简单的

大概是这样的:

$filepath = 'C:\test.txt'
$content  = Get-Content -Path $filepath -Raw
# build a template string for the NAT rules
$natRule = 'position {0} enabled {1} original-source "{2}" translated-source "{3}" ' +
           'original-destination "{4}" translated-destination: "{5}" '+
           'original-service "{6}" translated-service: "{7}" comment "{8}"'

# do some text splitting and replacing to create a Hashtable of values in each text block
$content -split 'IP version' | Where-Object { $_ -match '\S' } | ForEach-Object {
    # for each text block, take off the stuff starting at "----------Advanced----------",
    # remove the line "----------General----------",
    # replace the colons (:) with equal signs (=),
    # and convert this data into a Hashtable
    # the final replacement doubles any backslash because 
    # ConvertFrom-StringData regards them as regex escape characters
    $ht = 'IP version' + ($_ -split '\r?\n-+Advanced-+')[0] -replace 
          '\r?\n-+General-+' -replace ':', '=' -replace
          '\\', '\\' | ConvertFrom-StringData    

    # next build your nat rule command from the template using the values in the Hashtable
    $command = $natRule -f $ht.Index,
                           ($ht.'Enable NAT Policy').ToLower(),  # not sure if "True" needs to be lowercase here..
                           $ht.'Original Source', 
                           $ht.'Translated Source',
                           $ht.'Original Destination',
                           $ht.'Translated Destination',
                           $ht.'Original Service',
                           $ht.'Translated Service',
                           $ht.Comment

    # show the command we've built
    Write-Host "add nat-rule $command"

    # execute the command via API
    # Uncomment if you know what you're doing ;)
    # add nat-rule $command
}
屏幕上生成的命令如下所示:

add nat-rule position 1 enabled true original-source "Any" translated-source "ORIGINAL" original-destination "192.168.1.1" translated-destination: "ORIGINAL" original-service "IKE" translated-service: "ORIGINAL" comment "IKE NAT"

add nat-rule position 2 enabled true original-source "Source" translated-source "COPY" original-destination "192.168.1.2" translated-destination: "ORIGINAL" original-service "IKE&TINA" translated-service: "ORIGINAL" comment "IKE NOT"

另外,代码-replace'\\','\\'看起来可能很神奇,但是由于-replace使用正则表达式,我们需要用另一个反斜杠来逃避第一部分中的反斜杠。所做的是将所有反斜杠加倍

我已成功生成以下脚本。也许它有点不雅或粗糙,但它确实起作用了

谢谢大家的帮助和提示

$filepath = 'C:\test.txt'
$getfile = Get-Content $filepath -Raw
$splitfile = $getfile -split 'IP Version     : '

#Assignment of variables for regex part
$regex_index = 'Index     : '
$regex_original_source = 'Original Source     : '
$regex_translated_source = 'Translated Source     : '
$regex_original_destination = 'Original Destination     : '
$regex_translated_destination = 'Translated Destination : '
$regex_original_service = 'Original_Service     : '
$regex_translated_service = 'Translated_Service     : '
$regex_comment = 'Comment     : '

#Loop for each line of the text

foreach($object in $splitfile){
#Split the file for each line and analyze for each regex, if present, the output might be performed via CLI
$lines = $object.Split([Environment]::NewLine)

$data_index=@($lines) -match $regex_index
$value_index = $data_index -replace $regex_index, ''
#Write-Host $value_index

$data_original_source=@($lines) -match $regex_original_source
$value_original_source = $data_original_source -replace $regex_original_source, ''
#Write-Host $value_original_source

$data_translated_source=@($lines) -match $regex_translated_source
$value_translated_source = $data_translated_source -replace $regex_translated_source, ''
#Write-Host $value_translated_source

$data_original_destination=@($lines) -match $regex_original_destination
$value_original_destination = $data_original_destination -replace $regex_original_destination, ''
#Write-Host $value_original_destination

$data_translated_destination=@($lines) -match $regex_translated_destination
$value_translated_destination = $data_translated_destination -replace $regex_translated_destination, ''
#Write-Host $value_translated_destination

$data_original_service=@($lines) -match $regex_original_service
$value_original_service = $data_original_service -replace $regex_original_service, ''
#Write-Host $value_original_service

$data_translated_service=@($lines) -match $regex_translated_service
$value_translated_service = $data_translated_service -replace $regex_translated_service, ''
#Write-Host $value_translated_service

$data_comment=@($lines) -match $regex_comment
$value_comment = $data_comment -replace $regex_comment, ''
#Write-Host $value_comment

#Create string for variable assignment and print
$string = "add nat-rule position $value_index enabled true original-source `"$value_original_source`" translated-source `"$value_translated_source`" original-destination `"$value_original_destination`" translated-destination `"$value_translated_destination`" original-service `"$value_original_service`" translated-service `"$value_translated_service`" comments `"$value_comment`"

Write-Host $string

堆栈溢出问题的典型格式是,我已经编写了这段代码来解决这个问题,这是我所能做到的,现在我陷入了这样那样的困境。不是我有这个问题,请为我写一些代码。谢谢Tomalak,对不起。我编辑了这个问题,希望它更好看。所以在您的输入规则库中有多个这样的部分,对吗?对。对于每个部分,我想基于匹配的正则表达式分配一个变量,并使用该变量打印出所需的输出。至少-这是一个想法,然后第一步将是读取输入文件使用获取内容文件名-Raw和-split它的IP版本。这将为您提供一个节数组。然后在这些部分上循环,应用一组简单的正则表达式来提取各个值。我已经尝试了您的解决方案,但是它给了我一个关于$ht变量的错误。错误是在模式末尾分析\-invalical\。我正在尝试修复此问题,但我不确定是否应将其中的两个命令放在一个引号中,例如$ht.“Comment”或其他内容。我试过这个,但不起作用。有什么想法吗?@Alessandro I能够重现该错误,以防文本中的原始目的地不包含IP地址,而是包含某些服务器的名称,如原始目的地:\\server。为此,我在代码中添加了一个额外的-replace来加倍反斜杠,因为ConvertFrom StringData将它们视为正则表达式转义字符。。只有当属性名称中包含空格字符时,才需要单引号。不过,在所有属性上使用引号不会有任何伤害。谢谢西奥。我已经在下面的回答中制作了脚本,它完成了任务。我选择你的答案作为最佳答案,因为它是最有帮助的。谢谢