How can I use findstr with newline regular expression

后端 未结 4 1255
天涯浪人
天涯浪人 2020-12-21 14:51

I\'m on windows dos prompt. I have log file which contains log like:

Timestamp: Order received for Item No. 26551
Timestamp: Exception: OutOfRangeException
T         


        
相关标签:
4条回答
  • 2020-12-21 15:12

    If you can download tools, here's a Ruby for Windows command you can use.

    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
    
    0 讨论(0)
  • 2020-12-21 15:14

    If you are on Vista or Windows 7 (or if you install it manually on XP), you can use PowerShell for this:

    $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 will then contain a list of all item numbers that follow a line with Exception in it.

    0 讨论(0)
  • 2020-12-21 15:16

    I've discovered an undocumented feature - FINDSTR CAN match new line characters <CR> and <LF> and continue the match on subsequent lines. But the search string must be specified on the command line, the new line characters must be in variables, and the values must be passed via delayed expansion.

    Another complication is the IN() clause of a FOR loop is executed in a separate implicit CMD session, and the delayed expansion must be re-enabled. Also, the ! characters must be escaped so that they make it through to the 2nd CMD session.

    This little test script does the trick.

    @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
    


    EDIT 2015-01-11

    I just reread the question, and realize I got it wrong. The OP wanted the Item Number where the Exception string appears on the prior line (look behind search), but my solution can only find the Item Number where Exception appears on the subsequent line (look ahead search).

    Unfortunately, there is no way to get FINDSTR to do a look behind search.

    Under most circumstances, I would delete the answer above, since it does not answer the question. However, this answer does document a novel FINDSTR functionality that had not been described before that could be very useful. The look ahead feature is close enough in concept to the look behind feature that someone that needs it might find the answer via this question, so I plan to keep it.

    I do have a purely script based solution that runs on any Windows machine from XP onward, but it does not use FINDSTR. JREPL.BAT is a regular expression command line that can easily extract the desired Item Numbers.

    jrepl "Item No\. (\d+)\r\n.* Exception: " $1 /m /jmatch /f test.txt
    
    0 讨论(0)
  • 2020-12-21 15:18

    I had a look into the findstr documentation and I think it is not able to do a multiline search.

    Probably you should use more advanced tools like awk, or some versions of grep seems to support multiline regex too.

    You can have a look at stackoverflow.com/questions/152708/

    0 讨论(0)
提交回复
热议问题