代码之家  ›  专栏  ›  技术社区  ›  d4nt

如何在PowerShell中提取regex backreference/match的值

  •  19
  • d4nt  · 技术社区  · 16 年前

    我有一个包含数据行的文本文件。我可以使用以下PowerShell脚本提取我感兴趣的行:

    select-string -path *.txt -pattern "subject=([A-Z\.]+),"
    

    一些示例数据如下:

    blah blah subject=THIS.IS.TEST.DATA, blah blah blah
    

    我想要的是只提取主题的实际内容(即“this.is.test.data”字符串)。我试过这个:

    select-string -path *.txt -pattern "subject=([A-Z\.]+)," | %{ $_.Matches[0] }
    

    但“matches”属性始终为空。我做错什么了?

    8 回复  |  直到 9 年前
        1
  •  10
  •   dan-gph    16 年前

    我不知道你的版本为什么不起作用。它应该能工作。这是一个更丑陋的版本。

    $p = "subject=([A-Z\.]+),"
    select-string -path *.txt -pattern $p | % {$_ -match $p > $null; $matches[1]}
    

    编辑。 唐太斯的解释:

    -match 是与运算符匹配的正则表达式:

    >"foobar" -match "oo.ar"
    True
    

    这个 > $null 只抑制写入输出的真值。(尝试删除它。)有一个Cmdlet执行的操作与我目前不记得的名称相同。

    $matches 是保存最后一个结果的神奇变量 -匹配 操作。

        2
  •  4
  •   Philippe    15 年前

    在PowerShell v2 CTP3中,实现matches属性。因此,以下内容将起作用:

    select-string -path *.txt -pattern "subject=([A-Z\.]+)," | %{ $_.Matches[0].Groups[1].Value }
    
        3
  •  3
  •   Shay Levy    16 年前

    还有另一个选择

    gci *.txt | foreach { [regex]::match($_,'(?<=subject=)([^,]+)').value }
    
        4
  •  2
  •   JaredPar    16 年前

    您键入的代码的问题是,select字符串不会传递实际的regex对象。相反,它传递一个名为matchinfo的不同类,该类没有实际的regex匹配信息。

    如果您只想运行一次regex,那么就必须滚动您自己的函数,这并不太困难。

    function Select-Match() {
      param ($pattern = $(throw "Need a pattern"), 
             $filePath = $(throw "Need a file path") )
      foreach ( $cur in (gc $filePath)) { 
        if ( $cur -match $pattern ) { 
          write-output $matches[0];
        }
      }
    }
    
    gci *.txt | %{ Select-Match "subject=([A-Z\.]+)," $_.FullName }
    
        5
  •  2
  •   d4nt    16 年前

    从所有其他答案中学到了很多东西,我可以用下面的一行得到我想要的:

    gci *.txt | gc | %{ [regex]::matches($_, "subject=([A-Z\.]+),") } | %{ $_.Groups[1].Value }
    

    这感觉很好,因为我每行只运行一次regex,当我在命令提示下输入时,最好不要有多行代码。

        6
  •  1
  •   John D. Cook    16 年前
        7
  •  1
  •   freddymio    9 年前

    select string命令似乎返回 马奇诺 变量而不是“字符串”变量。 我花了好几个小时在论坛和官方网站上发现了这一点。 我还在收集信息。 解决此问题的一种方法是显式声明一个字符串变量,以保存从您的示例中选择字符串返回的结果:

    [弦乐] $foo=select string-path*.txt-pattern“主题=([a-z.]+),”

    $foo变量现在是字符串,而不是matchinfo对象。

    希望这有帮助。

    PS5 PowerShell版本5字符串操作

        8
  •  0
  •   Jeffrey Knight    15 年前

    另一个变体,匹配字符串中的7位数字

    echo "123456789 hello test" | % {$_ -match "\d{7}" > $null; $matches[0]}
    

    退货:1234567