【问题标题】:Combine two regex in PowerShell在 PowerShell 中结合两个正则表达式
【发布时间】:2019-11-26 13:51:51
【问题描述】:

这是我要解析的数据:

10.186.128.0/20 172.17.128.161 0 65000 8788

10.186.128.0/20 172.17.128.161 0 65000 878

10.186.128.0/20 172.17.128.161 0 65000 87

理想情况下,输出应与行首的 IP 地址以及最后 2 位或 3 位或 4 位数字相匹配。 所需输出示例:

10.186.128.0/20 8788

10.186.128.0/20 878

10.186.128.0/20 87

我有匹配 IP 地址"10\.\d*\.\d*\.\d*\/\d\d" 的正则表达式

然后我有第二个正则表达式将匹配最后 2 或 3 或 4 位数字" \d{4}$| \d{3}$| \d{2}$"

问题是如何在 PowerShell 中结合这两个正则表达式来达到预期的结果?

谢谢

【问题讨论】:

  • 可能是$s -replace '^(10(?:\.\d+){3}/\d+)\s.*\s(\d+)$', '$1 $2'?还是您的意思是文本包含需要首先提取的行?
  • 如果您尝试匹配 IP 地址,点之间的位数永远不会超过 3 位,并且永远不会小于 1。您应该将您的正则表达式更改为 10\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{2}
  • 酷。谢谢。我修改了我的 IP 匹配正则表达式。但是,如何实现获取 IP 以及字符串中的最后 2 位或 3 位或 4 位数字的预期结果?
  • 我为你创建了一个regex 101 来测试更多的案例,基本上,我添加了一个空格来匹配 2 到 4 位数字。
  • Select-String '(?m)^(10(?:\.\d+){3}/\d+)\s.*\s(\d+)\r?$' -input $txt -AllMatches | Foreach {$_.matches} | Foreach {$_.groups[1].value + " " + $_.groups[2].value}?注意$txt 这里是一个多行字符串输入。它在 PS 6.1.3 中输出预期结果

标签: regex powershell parsing select-string


【解决方案1】:

你可以使用

Get-Content $filepath | Select-String '^(10(?:\.\d+){3}/\d+)\s.*\s(\d+)$' -AllMatches | Foreach-Object {$_.Matches} | Foreach-Object {$_.Groups[1].Value + " " + $_.Groups[2].Value}

^(10(?:\.\d+){3}/\d+)\s.*\s(\d+)$ 正则表达式 - 参见 its online demo - 匹配:

  • ^ - 字符串开头
  • (10(?:\.\d+){3}/\d+) - 第 1 组:10,然后重复三个点和任何 1+ 位,然后 / 和 1+ 位
  • \s.*\s - 一个空格,除换行符之外的任何 0+ 字符和一个空格
  • (\d+) - 第 2 组:1 位以上
  • $ - 字符串结束。

所以,

  • Get-Content $filepath读取文件
  • Select-String '^(10(?:\.\d+){3}/\d+)\s.*\s(\d+)$' -AllMatches 通过逐行读取文件从文件中获取所有匹配项
  • Foreach-Object {$_.Matches} 一一抓取所有匹配项
  • Foreach-Object {$_.Groups[1].Value + " " + $_.Groups[2].Value} 连接第 1 组和第 2 组值。

【讨论】:

  • 这正是我想要的。谢谢。
【解决方案2】:

如果您的所有数据都始终采用发布的格式,则使用-split 似乎要简单得多。

Get-Content -Path file.txt |
    Foreach-Object { [string]($_ -split ' ')[0,-1] }

说明:

-split 使用正则表达式匹配将字符串拆分为字符串数组。在这里,字符串基于单个空格进行拆分。 [0,-1] 选择数组的第一个(索引 0)和最后一个(索引 -1)元素。

[string] 将两个数组元素转换为字符串。由于 PowerShell 在将两个项目转换为字符串时会自动用空格连接它们,因此这只是一种快捷方式。

【讨论】:

    【解决方案3】:

    如果只需要一种快速修改字符串的方法
    用这两个正则表达式之一进行简单替换:

    $string -replace '(?<=\b10\.\d{0,3}\.\d{0,3}\.\d{0,3}/\d{2}).*(?=[ \t]\d{1,4}\b)', ''
    

    $string -replace '(?m)(?<=^[ \t]*10\.\d{0,3}\.\d{0,3}\.\d{0,3}/\d{2}).*(?=[ \t]\d{1,4}[ \t]*$)', ''
    

    【讨论】:

    • 此解决方案将有效地删除我要检索的部分。 Wiktor Stribiżew 提供的解决方案工作得很好,所以它应该被标记为正确的答案恕我直言。
    • @JozefTrubac - 结果字符串是从行首开始的 IP 地址,也是最后 2 或 3 或 4 位数字。
    • @JozefTrubac - 我从不阅读或查看其他答案,因为我认为自己是专家。请参阅可能的duplicate
    猜你喜欢
    • 2015-01-14
    • 1970-01-01
    • 1970-01-01
    • 2012-03-14
    • 2016-10-23
    • 1970-01-01
    相关资源
    最近更新 更多