【问题标题】:How can I use findstr with newline regular expression如何将 findstr 与换行正则表达式一起使用
【发布时间】:2011-04-12 07:21:54
【问题描述】:

我在 windows dos 提示符下。我有日志文件,其中包含如下日志:

Timestamp: Order received for Item No. 26551
Timestamp: Exception: OutOfRangeException
Timestamp: Message: Inventory Item is not stock. Item No. 23423
Timestamp: Order received for Item No. 23341

我想提取所有给出某种异常的项目编号。我为此使用 findstr 命令。如何在正则表达式中使用换行符?我想要所有有异常字的行和下一行的项目号。

有什么帮助吗?

【问题讨论】:

  • @moderator:我可以结束这个问题吗?我们似乎走到了尽头。

标签: windows regex dos findstr


【解决方案1】:

我发现了一个未记录的功能 - FINDSTR CAN 匹配换行符 <CR><LF> 并在后续行中继续匹配。但搜索字符串必须在命令行中指定,换行符必须在变量中,并且值必须通过延迟扩展传递。

另一个复杂之处是 FOR 循环的 IN() 子句在单独的隐式 CMD 会话中执行,并且必须重新启用延迟扩展。此外,!必须对字符进行转义,以便它们进入第二个 CMD 会话。

这个小测试脚本可以解决问题。

@echo off
setlocal enableDelayedExpansion
if "%~1"==":doSearch" goto :doSearch

::Define a variable as a LineFeed (0x0A) character
set LF=^


:: The above 2 blank lines MUST be preserved!

::Define a CR variable as a CarriageReturn (0x0D) character
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"

set file="test.txt"
for /f "delims=" %%A in ('cmd /v:on /c^"findstr /rc:"Item No\. .*^!CR^!*^!LF^!.* Exception: " %file%^"') do (
  set "ln=%%A"
  set "item=!ln:*Item No. =!"
  echo Item No. !item! had an exception
)
exit /b


编辑 2015-01-11

我只是重读了这个问题,然后意识到我弄错了。 OP想要异常字符串出现在前一行的项目编号(查找后搜索),但我的解决方案只能找到异常出现在后续行的项目编号(向前搜索)。

很遗憾,无法让 FINDSTR 查看搜索结果。

在大多数情况下,我会删除上面的答案,因为它没有回答问题。但是,这个答案确实记录了一个以前没有描述过的新颖的 FINDSTR 功能,它可能非常有用。前瞻功能在概念上与后瞻功能非常接近,需要它的人可能会通过这个问题找到答案,所以我打算保留它。

我确实有一个纯粹的基于脚本的解决方案,它可以在从 XP 开始的任何 Windows 机器上运行,但它不使用 FINDSTR。 JREPL.BAT 是一个正则表达式命令行,可以轻松提取所需的项目编号。

jrepl "Item No\. (\d+)\r\n.* Exception: " $1 /m /jmatch /f test.txt

【讨论】:

  • 我可以自定义它以在文本文件中搜索像 Hello(return)there 这样的字符串吗?
【解决方案2】:

我查看了findstr documentation,我认为它无法进行多行搜索。

您可能应该使用更高级的工具,例如 awk,或者某些版本的 grep 似乎也支持多行正则表达式。

你可以看看stackoverflow.com/questions/152708/

【讨论】:

  • 谢谢。我想使用 dos 命令执行此操作的原因是我不想编写繁重的代码来解析文本文件。我有点意识到 findstr 不能那样做 :( 只是想知道,以前是否有人这样做过。无论如何,我需要逃避它。我用 VBScript 做到了。
  • @Morin:您可以并且应该发布您的解决方案。 VBScript 无疑是一个好主意。如果它是对您帮助最大的解决方案,您甚至可以接受自己的解决方案(这里似乎就是这种情况)。只要您有足够的声誉,您就可以投票其他对您也有帮助的答案。
【解决方案3】:

另一个 powershell 示例,具有积极的后视:

'Timestamp: Order received for Item No. 26551
Timestamp: Exception: OutOfRangeException
Timestamp: Message: Inventory Item is not stock. Item No. 23423
Timestamp: Order received for Item No. 23341
Timestamp: Exception: OutOfRangeException
Timestamp: Message: Inventory Item is not stock. Item No. 23424' | 
  set-content input.txt

get-content -raw input.txt | 
  select-string -allmatches '((?<=exception.*\n.*)\d+)' | 
  % matches | % value
23423
23424

【讨论】:

    【解决方案4】:

    如果您使用的是 Vista 或 Windows 7(或者如果您在 XP 上手动安装),则可以使用 PowerShell:

    $resultlist = new-object System.Collections.Specialized.StringCollection
    $regex = [regex] '(?m)^.*Exception.*\r\n.*Item No\. (\d+)'
    $match = $regex.Match($subject)
    while ($match.Success) {
        $resultlist.Add($match.Groups[1].Value) | out-null
        $match = $match.NextMatch()
    } 
    

    $resultlist 将包含所有项目编号的列表,其中包含Exception

    【讨论】:

      【解决方案5】:

      如果你可以下载工具,这里有一个Ruby for Windows 命令你可以使用。

      C:\work>ruby -ne "print gets.split.last if /Exception/" file
      23423
      C:\work>type file
      Timestamp: Order received for Item No. 26551
      Timestamp: Exception: OutOfRangeException
      Timestamp: Message: Inventory Item is not stock. Item No. 23423
      Timestamp: Order received for Item No. 23341
      
      C:\work>ruby -ne "print gets.split.last if /Exception/" file
      23423
      

      【讨论】:

      • 那是我不想要的。我只是想用我在客户端机器上的任何东西来解析一个文本文件。不过,感谢您的回答
      猜你喜欢
      • 1970-01-01
      • 2017-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-18
      • 2016-12-29
      • 2011-06-19
      • 2012-06-23
      相关资源
      最近更新 更多