在带有回车的文本中使用正则表达式

问题描述

我正在使用 powershell 在 txt 中使用正则表达式,但只有当文本不包含回车时它才有效。我准备了一个这样的示例文件

the duck is on the table --found!  

the elephant is on  the table --found! 

the cat is  
on the table --NOT found!  :-(

the lion is on the tablet --NOT found but ok ;-)

the dog is on  
the table               --NOT found!  :-(

the turtle isonthe table --NOT found but ok ;-)

the cow is on the              table --found! 

我想要包含“在桌子上”的案例,所以我执行这个:

select-string -path "c:\example.txt" -pattern '([^\w]{1})on([^\w])+the([^\w])+table([^\w]{1})'

这是输出


example.txt:1:鸭子在桌子上--找到了!

example.txt:2:大象在桌子上--找到了!

example.txt:14:牛在桌子上--找到了!


但我也需要带回车的箱子!猫在哪里?狗在哪里?

谢谢;-)

解决方法

我不确定使用 Select-String 是否可行,因为它逐行读取文件,而不是将文件作为单个多行 string 读取,但这对我有用:

$tmp = New-TemporaryFile

@'
the duck is on the table 

the elephant is on the table 

the cat is
on the table

the lion is on the tablet

the dog is on
the table

the turtle isonthe table

the cow is on the table 
'@ | Set-Content $tmp


$content = Get-Content $tmp -Raw
[regex]::Matches($content,'.*[^\w]on[^\w]+the[^\w]+table[^\w].*') |
Select-Object Index,Value | Format-Table -Wrap

结果:

Index Value                         
----- -----                         
    0 the duck is on the table      
   29 the elephant is on the table  
   62 the cat is                    
      on the table                  
  119 the dog is on                 
      the table                     
  175 the cow is on the table   

如果您只想在单词之间使用空格可能会更好:

'.*\son\s+the\s+table\s.*'

如果你想不区分大小写:

[regex]::Matches($content,'.*[^\w]on[^\w]+the[^\w]+table[^\w].*',[System.StringComparison]::OrdinalIgnoreCase)
,

使用通过 Select-String-Path-LiteralPath 参数提供的文件输入,目标文件被一行一行地处理 ,正如 Santiago Squarzon's helpful answer 中所指出的那样。

为了匹配模式跨行,文件的内容必须作为单行多行字符串传递,这就是{{3} } 的 -Raw 开关确实

此外,为了报告该多行字符串内的多个匹配项,必须使用Select-String的{​​{1}}开关

然后可以通过 -AllMatches 输出的 Get-Content 实例的 .Matches 属性处理结果匹配:

Select-Object

有关上面使用的 Microsoft.PowerShell.Commands.MatchInfo 的说明,请参阅 regex[1]

以上产生:

Get-Content -Raw example.txt | 
  Select-String -AllMatches '(?m)^.*?\son\s+the\s+table\b.*$' |
    ForEach-Object {
      foreach ($match in $_.Matches) {
        "[$($match.Value)]"
      }
    }

[1] 请注意,尽管 this regex101.com page 是一个用于可视化、解释和试验正则表达式的站点,但不支持 PowerShell 使用的 .NET 正则表达式引擎,选择类似的引擎,例如 Java 引擎,通常表现出相同的行为,至少在根本上是相同的。