【问题标题】:Powershell multiline regexPowershell 多行正则表达式
【发布时间】:2015-12-02 21:21:22
【问题描述】:

我正在尝试从以下示例中获取完整的错误:

date time somemethod EXC somenumber sometext  R:System.NullReferenceException: Object reference not set to an instance of an object.
   at sometext in somepath .cs:line somenumber System.NullReferenceException: Object reference not set to an instance of an object.
   at sometext in Somepath .cs:line somenumber 

从那以后,我想得到EXC 之后直到cs:line somenumber 的所有内容。

01/01/01 date (mode) (status) (somenumber) (name+error),这里通常有一个新行继续错误消息,并以字符 cs:line (number) 结尾。

我设法收到错误消息,因为它总是以 EXC 开头(所以正则表达式是 EXC .*,但是我无法获得带有代码的完整消息。我只能访问 PowerShell 2.0,我正在使用以下公式:

$Filecontent = [io.file]::Readalltext("path to file")
$filecontent | select-string 'EXC .*' -allmatches |
  foreach {$_.Matches} | Foreach {$_.Value} > errors.txt

我需要的是获取行号的完整错误,但我有正确的正则表达式问题。我不关心日期、时间、模式,正则表达式应该获得 EXC 状态并使用 line 获取完整消息。

使用正则表达式 'EXC .*\n.*cs:line [0-9]{0,99}' 后,它会为我找到那些在一行完成后出现错误消息的消息,但是,有时会有更多的下一行我也想捕捉。 有什么想法吗?

【问题讨论】:

  • 公式中的错字,已修复:$Filecontent = [io.file]::Readalltext("path to file") $filecontent |选择字符串'EXC。' -allmatches | foreach {$_.Matches} | Foreach {$_.Value} > errors.txt

标签: regex powershell powershell-2.0


【解决方案1】:

如果您将错误(堆栈跟踪)定义为

  • 在第 1 列中以非空白字符开头
  • 跨越多行
  • 属于错误的每一行都缩进 3 个空格

那么捕获这样一个块的正则表达式如下所示:

(?m)^\S.*(\s*^   \S.*)+

在您检索到完整的堆栈跟踪块后,您可以在第二步中使用类似这样的方法选择行号:

at (.*?) in (.*?):line (\d+)

表达式分解为:

(?m)         # inline flag: multiline mode
^            # start-of-line
\S           # a non-whitespace character
.*           # anything up to the end of the line
(            # group 1
  \s*        #   any number of whitespace (this matches newline character)
  ^          #   start-of-line
             #   3 spaces
  \S         #   a non-whitespace character
  .*         #   anything up to the end of the line
)+           # end of group 1, repeat at least once

比较:https://regex101.com/r/rW1hD6/1

【讨论】:

  • 我想定义如下: - 以 EXC 和一个空格开头 - 跨越多行 - 以 cs:line 结尾(最多四位数字)
  • 我的表达式捕获了这些的超集。如果需要,请使其更具体,例如将EXC 放入适当的位置。或者让Select-String 首先获取所有堆栈跟踪,然后通过Where-Object 将它们通过管道传输。有很多方法可以做到这一点。
  • 嗯,我可能做错了什么,但是当我使用 '^\S.*(\s*^ \S.*)+' 时,它没有检索到任何东西。据我所知,在 () 里面有 3 个空格?
  • 是的,三个空格。你注意到“多行”部分了吗?我不认为Select-String 有一个开关,但你可以在正则表达式本身中启用它,方法是在它前面加上(?m),比如(?m)^\S.*(\s*^ \S.*)+。这个开关很关键,否则你不能在同一个表达式中有多个^
  • 太好了,非常感谢 Tomalak。您能否向我解释一下这个正则表达式,因为我还在学习,我发现的只是 \s 是空格,而 \S 不是空格,它有点不清楚它是如何完成这项工作的,但是这个公式:select-string' (?m)^\S.*(\s*^ \S.*)+' -allmatches | foreach { {$_.Matches} | foreach {$_.Value} > file.txt 完成工作(所有类型的错误,所有新行和代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多