使用 Powershell 和 Regex 从文本文件中提取行块

Use Powershell and Regex to extract block of lines from a text file

我正在开发 Powershell 脚本和 .Net Regex,以使用 powershell 和 regex 在网络设备配置中查找模式匹配。我在尝试从配置文件中提取一段字符串时遇到问题,并且在编写正则表达式语句以匹配回车 return 和新行时遇到问题。下面是我的例子。我有一个配置文件,其中包含我要提取的信息

vlan no  description  ports
999      unused       Gi1/2,Gi1/3, Gi1/4, Gi1/5, Gi1/6, Gi/7, Gi/8, Gi1/9
                      Gi1/0, Gi1/11, Gi1/12, Gi1/13, Gi1/14, Gi1/15, Gi1/16
                      Gi1/17, Gi1/18

这是我的代码

$File = Get-content C:\config.txt

$Regex = "(?sm)(^999.*(\r\n\s+.*)"
$unused_ports = Select-String -path $File -Pattern $Regex 
Write-host $Unused_ports

只显示第一行

999      unused       Gi1/2,Gi1/3, Gi1/4, Gi1/5, Gi1/6, Gi/7, Gi/8, Gi1/9

我也尝试了下面的 $Regex

$Regex = '(?m)(^999.*\s+Gi1/10.*)
$Regex = '(?m)(^999.*\r\n\s+Gi1/10.*)

但是 none 我使用的正则表达式提取了所有端口(3 行)

我也使用了 get-content c:\config.txt -raw 但这会显示配置文件中的所有内容。

如果有人可以帮助提取所有三行端口号以及如何使用回车 return 和换行来匹配新行,我将不胜感激。

Wiktor Stribiżew 在对问题的评论中提供了关键指针[1] : 您必须使用 Get-Content -Raw 将文件内容读入 单个 字符串,以便您的正则表达式可以匹配 跨行 :

if ((Get-Content -Raw C:\Config.txt) -match '(?ms)^999.*?(?=\r?\n\S|\Z)') { 
  $Matches[0]  # automatic variable $Matches reflects what was captured
}

正则表达式也需要一些调整,包括使用 non-greedy 量词 .*?,如 TheMadTechnician 所建议:

  • (?ms) 设置正则表达式选项 m(将 ^$ 视为 line 锚点)和 s(使 . 也匹配 \n(换行符)`。

  • ^999.*? 匹配以 999 开头的任何行以及任何后续字符 non-greedily.

  • (?=\r?\n\S|\Z) 是正 look-ahead 断言 ((?=...)) 匹配换行符 (\r?\n) 后跟一个 non-whitespace 字符 (\S) - 假设是 next 块的开始 - 或者 (|)输入的结尾 (\Z) - 实际上,这匹配文件的结尾或下一个块的开头,但不将其包含在 $Matches.[=32 中记录的匹配中=]


[1] Wiktor 还建议正则表达式 (?m)^999.*(?:\r?\n.*){2},它适用于示例输入,但仅限于恰好有 3 行的块 - 相比之下,此处提供的解决方案发现任何长度的块,只要 non-initial 块行都具有前导空格。