Powershell – 分隔输出并操作数据内部

huangapple go评论77阅读模式
英文:

Powershell - Delimit output and manipulate data inside

问题

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

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

IP版本:IPv4
索引:1
----------常规----------
原始源:任何
转换源:原始
原始目标:192.168.1.1
转换目标:原始
原始服务:IKE
转换服务:原始
入站接口:任何
出站接口:任何
注释:IKE NAT
启用NAT策略:True
系统策略:True
----------高级----------
[...](无关的数据)

我想要实现的目标是获取所有这些数据并根据其创建一个命令,该命令将自动通过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"

此规则的位置应基于“Index”变量。

我基本上卡在了如何告诉程序:“部分以'IP版本'开头,并以'System Policy:...'结束”。

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

如何在PowerShell中实现这一目标?

到目前为止,我已经制作了以下脚本:

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

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

提前感谢。

英文:

I am trying to create a Powershell script which, based on an input TXT or CSV, splits it into sections which are delimited by specific regexes and then manipulates the data inside it based on other regexes.

To be more specific, I'm trying to manipulate data from a NAT rulebase, which is formatted like so:

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)

What I'm trying to achieve, is get all that data and manipulate it in order to create a command which will add that rule automatically via API on another firewall for all the NAT rules which are present within the TXT file, so for this example:

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"

The position of this rule should be based on the "Index" variable.

I'm basically stuck in saying the program: "The sections start with 'IP version' and end with 'System Policy : ...' "

For each of these sections, I believe I can assign a regex to a variable and if it matches, it assigns the value to a new variable.

How can I achieve this, by using Powershell?

So far, I've managed to produce the following script:

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

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

Thanks in advance.

答案1

得分: 1

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

当这些操作完成后,我认为最简单的方法是使用 ConvertFrom-StringData 命令来获取哈希表中的所有值,并使用哈希表中的值来构建命令字符串来填充模板字符串。

类似这样的代码:

$filepath = 'C:\test.txt'
$content  = Get-Content -Path $filepath -Raw
# 为NAT规则构建一个模板字符串
$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}"'

# 对文本进行拆分和替换以创建每个文本块中的值的哈希表
$content -split 'IP version' | Where-Object { $_ -match '\S' } | ForEach-Object {
    # 对于每个文本块,去掉从"----------Advanced----------"开始的部分,
    # 移除行"----------General----------",
    # 将冒号(:)替换为等号(=),
    # 并将此数据转换为哈希表
    # 最后一个替换会使反斜杠翻倍,因为ConvertFrom-StringData将其视为正则表达式转义字符
    $ht = 'IP version' + ($_ -split '\r?\n-+Advanced-+')[0] -replace 
          '\r?\n-+General-+', -replace ':', '=' -replace
          '\\', '\\' | ConvertFrom-StringData    

    # 接下来,使用哈希表中的值从模板构建您的NAT规则命令
    $command = $natRule -f $ht.Index,
                           ($ht.'Enable NAT Policy').ToLower(),  # 不确定是否需要在此处将"True"转换为小写..
                           $ht.'Original Source', 
                           $ht.'Translated Source',
                           $ht.'Original Destination',
                           $ht.'Translated Destination',
                           $ht.'Original Service',
                           $ht.'Translated Service',
                           $ht.Comment

    # 显示我们构建的命令
    Write-Host "add nat-rule $command"

    # 通过API执行命令
    # 如果您知道您在做什么,取消注释 ;)
    # 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"

P.S. 代码-replace '\\', '\\' 看起来可能有些荒谬,但由于-replace使用正则表达式,我们需要使用另一个反斜杠来转义第一部分中的反斜杠。它的作用是使所有反斜杠翻倍。

英文:

To parse a file like that, you indeed need to do some splitting and replacing.

When that is done, I think it would be easiest to use the ConvertFrom-StringData cmdlet to get all the values in a Hashtable and fill a template string using the values in that hash to build your command string.

Something like this:

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

The resulting commands on screen wil look like:

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"

<sup>P.S. The code -replace &#39;\\&#39;, &#39;\\&#39; seems rediculous perhaps, but since -replace uses Regex, we need to escape the backslash in the first part with yet another backslash. What is does is doubling all backslashes</sup>

答案2

得分: 0

I've managed to produce the following script. Maybe it's a bit inelegant or crude, but it does the job.

Thanks all for your help and hints.

$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
}
英文:

I've managed to produce the following script. Maybe it's a bit inelegant or crude, but it does the job.

Thanks all for your help and hints.

$filepath = &#39;C:\test.txt&#39;
$getfile = Get-Content $filepath -Raw
$splitfile = $getfile -split &#39;IP Version     : &#39;
#Assignment of variables for regex part
$regex_index = &#39;Index     : &#39;
$regex_original_source = &#39;Original Source     : &#39;
$regex_translated_source = &#39;Translated Source     : &#39;
$regex_original_destination = &#39;Original Destination     : &#39;
$regex_translated_destination = &#39;Translated Destination : &#39;
$regex_original_service = &#39;Original_Service     : &#39;
$regex_translated_service = &#39;Translated_Service     : &#39;
$regex_comment = &#39;Comment     : &#39;
#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, &#39;&#39;
#Write-Host $value_index
$data_original_source=@($lines) -match $regex_original_source
$value_original_source = $data_original_source -replace $regex_original_source, &#39;&#39;
#Write-Host $value_original_source
$data_translated_source=@($lines) -match $regex_translated_source
$value_translated_source = $data_translated_source -replace $regex_translated_source, &#39;&#39;
#Write-Host $value_translated_source
$data_original_destination=@($lines) -match $regex_original_destination
$value_original_destination = $data_original_destination -replace $regex_original_destination, &#39;&#39;
#Write-Host $value_original_destination
$data_translated_destination=@($lines) -match $regex_translated_destination
$value_translated_destination = $data_translated_destination -replace $regex_translated_destination, &#39;&#39;
#Write-Host $value_translated_destination
$data_original_service=@($lines) -match $regex_original_service
$value_original_service = $data_original_service -replace $regex_original_service, &#39;&#39;
#Write-Host $value_original_service
$data_translated_service=@($lines) -match $regex_translated_service
$value_translated_service = $data_translated_service -replace $regex_translated_service, &#39;&#39;
#Write-Host $value_translated_service
$data_comment=@($lines) -match $regex_comment
$value_comment = $data_comment -replace $regex_comment, &#39;&#39;
#Write-Host $value_comment
#Create string for variable assignment and print
$string = &quot;add nat-rule position $value_index enabled true original-source `&quot;$value_original_source`&quot; translated-source `&quot;$value_translated_source`&quot; original-destination `&quot;$value_original_destination`&quot; translated-destination `&quot;$value_translated_destination`&quot; original-service `&quot;$value_original_service`&quot; translated-service `&quot;$value_translated_service`&quot; comments `&quot;$value_comment`&quot;
Write-Host $string

huangapple
  • 本文由 发表于 2020年1月3日 20:53:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/59579004.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定