【问题标题】:Powershell Regex Multiline parsingPowershell 正则表达式多行解析
【发布时间】:2021-07-22 07:38:11
【问题描述】:

我正在构建一个脚本,该脚本将分析配置文件(cisco 交换机配置)并根据某些发现构建报告。遗憾的是,必须将调查结果记录在特定的表格上,所以除了手动生成每个表格之外,这条痛苦的道路是我唯一的选择。

我正在尝试做的事情: 使用以下内容,我试图将以下多行表达式拉入 PS 进行评估

interface vlan1
no ip address
shutdown
!

我找到了多个指向两个选项之一的来源-第一个(也是最简单的)是使用“-raw”开关将文件加载到 Get-content 中,以便将整个文件评估为单个字符串,并且然后使用“select-string”命令输出我要查找的具体信息。

我的基本代码如下所示

if (get-content -path U:\Testing\Test.txt -Raw | select-string -Pattern "(?ms)interface vlan1.*no ip address.*(?!no shutdown)shutdown.*\!" -Quiet)
{
write-host('pass')
}
else
{
write-host('fail')
}

预期结果:如果字符串为真 - 我会将结果附加到文件(我已经拥有的那部分)

如果配置不包含专门的“关闭”(没有单词 no),那么它将被注释为这样(我也有这个过程)

在此先感谢您的帮助 - 希望本文简洁明了。

进一步明确:脚本返回误报/误报。在 if 命令之外运行 get-content + select-string 时,我基本上得到 -raw 输出,但字符串本身不匹配,这让我相信我在行首(接口 vlan1)上遇到问题和结束行(!)

我已经尝试过使用正则表达式字符串的结构来尝试梳理出一个解决方案,但是对于使用 select-string 时多行输出的使用我仍然有点模糊。

【问题讨论】:

    标签: powershell


    【解决方案1】:
    • 由于您需要查看文件完整,没有理由使用Select-String cmdlet,因为-match,正则表达式匹配运算符,更有效地处理已经在内存中的字符串。

      • 注意:-match 只有每个找到 一个 匹配项(如果有);如果这还不够,请使用[regex]::Matches() .NET 方法;不幸的是,没有 operator 用于多个匹配项; GitHub issue #7867 建议引入一个,命名为-matchall
    • 由于.* 跨行,由于(?s) 匹配选项,您的正则表达式过于宽松(贪婪),因此匹配发生跨行多个块

    以下使用不带.* 的正则表达式,而是显式匹配所有行,包括显式匹配插入的换行符 (\r?\n)。[1]

    这适用于您的示例输入,但您可能需要调整正则表达式(省略(?s) 选项使.* 仅匹配intra-行;表达式可以设为非-greedy 通过使用? 修改重复符号(例如.*?))。

    $re = '(?m)^interface vlan1\r?\nno ip address\r?\n(?!no shutdown)shutdown\r?\n!'
    if ((Get-Content U:\Testing\Test.txt -Raw) -match $re) {
     # ... 
    }
    

    注意:假设没有必要验证尾随 ! 是其行中的唯一字符;如果需要,请附加 (?:\r?\n|\z)[2]


    [1] 此正则表达式匹配两种常见的换行符格式:CRLF(\r\n,Windows)和 LF(\n,Unix)。

    [2] 不幸的是,如果输入使用 ,使用 $ 断言行尾((?m) 选项有效)可能不起作用 CRLF (\r\n) 换行符,因为$ 仅匹配 LF 字符 (\n) 的位置,这意味着 $ 在 @ 之后不会立即匹配 987654349@,由于介入了\r

    【讨论】:

    • 很好,@SteveMartin - $ 仅适用于 LF-only 换行符 - 请参阅我的更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多