Search code examples
windowsbatch-filecmdfindstr

What is the proper syntax for FINDSTR /E in BATCH to match strings that are at the end of a line?


I'm writing a subroutine in Batch that will extract text in the middle of a string, and can accept two sets of characters (like a word or phrase), rather than individual delimiters, as its arguments. In addition, I'd like to get the index position of the first character of the lookup value. The way I'm going to do this is by looping through characters and eliminating it one by one from both sides until the lookup string sets match the beginning and end of the surviving string.

Character elimination is done using variable offset/index like in this one: !_str:~%_idx%!, where _str is the string to search, and _idx is the offset count, then pipe it to FINDSTR /B to see if the lookup string matches the beginning characters of the surviving string from the loop. So far, no problem. But when I do the process for the second lookup string to the right side of the string being searched, and piped it to FINDSTR /E to see if the second lookup string matches the end of the surviving string from the loop, it doesn't seem to work.

From my understanding from these sources,

  • Command Prompt > FINDSTR /?
  • FINDSTR

FINDSTR switches /B and /E match lookup strings that are at the beginning and end of a line, respectively.

So, out of desperation, I created some tests with different variations even though I know that these variations are not the issue, but I still did it, anyway. Here's what I've tried so far:

title FINDSTR_TEST
echo off
cls

setlocal EnableDelayedExpansion

set "_str=Hello World"

echo String to search: %_str%
echo:
echo Matches pattern if at the BEGINNING of a line.
echo 1: & echo %_str% | findstr /b "Hello"
echo 2: & echo %_str% | findstr /b /l "Hello"
echo 3: & echo %_str% | findstr /b /C:"Hello"
echo:
echo:
echo Matches pattern if at the END of a line.
echo 1: & echo %_str% | findstr /e "World"
echo 2: & echo %_str% | findstr /e /l "World"
echo 3: & echo %_str% | findstr /e /C:"World"
echo:
echo ERRORLEVEL: %errorlevel%

pause
endlocal
exit

Here's the actual result:

String to search: Hello World

Matches pattern if at the BEGINNING of a line.
1:
Hello World
2:
Hello World
3:
Hello World


Matches pattern if at the END of a line.
1:
2:
3:

ERRORLEVEL: 1
Press any key to continue . . .

But this is what I was expecting:

String to search: Hello World

Matches pattern if at the BEGINNING of a line.
1:
Hello World
2:
Hello World
3:
Hello World


Matches pattern if at the END of a line.
1:
Hello World
2:
Hello World
3:
Hello World

ERRORLEVEL: 1
Press any key to continue . . .

Two quick questions here:

  1. Is there any problem with my code especially where /E switch is being used?
  2. Aren't these /L and /C:string switches redundant? It appears to me that they do the same thing.

Any clarifications on these matter will be appreciated.

Thank you all very much.


Solution

  • As a follow up of my comment, you should be able to see exactly what is happening, if you create a three line batch file, exactly like this:

    Echo Hello World | FindStr /B "Hello"
    (Echo Hello World) | FindStr /E "World"
    @Pause
    

    The output will show whitespace, where you didn't specifically add it:

    
    C:\Users\SpaghettiCode>Echo Hello World   | FindStr /B "Hello"
    Hello World
    
    C:\Users\SpaghettiCode>(Echo Hello World )  | FindStr /E "World"
    Press any key to continue . . .
    

    My preferred solution, is to use Set /P instead of Echo, because the output can be specifically terminated using doublequotes, and redirection. For example:

    @Echo Off
    SetLocal EnableExtensions
    Title FINDSTR_TEST
    ClS
    Set "_str=Hello World"
    Echo String to search: %_str%
    Echo(
    Echo Matches pattern if at the BEGINNING of a line.
    Echo 1:& Set /P "=%_str%" 0< NUL | %SystemRoot%\System32\findstr.exe /B /I /R "Hello"
    Echo 2:& Set /P "=%_str%" 0< NUL | %SystemRoot%\System32\findstr.exe /B /I /L "Hello"
    Echo 3:& Set /P "=%_str%" 0< NUL | %SystemRoot%\System32\findstr.exe /B /I /R /C:"Hello"
    Echo 4:& Set /P "=%_str%" 0< NUL | %SystemRoot%\System32\findstr.exe /I /R "^Hello"
    Echo 5:& Set /P "=%_str%" 0< NUL | %SystemRoot%\System32\findstr.exe /I /R "^Hello\>"
    Echo(
    Echo(
    Echo Matches pattern if at the END of a line.
    Echo 1:& Set /P "=%_str%" 0< NUL | %SystemRoot%\System32\findstr.exe /E /I /R "World"
    Echo 2:& Set /P "=%_str%" 0< NUL | %SystemRoot%\System32\findstr.exe /E /I /L "World"
    Echo 3:& Set /P "=%_str%" 0< NUL | %SystemRoot%\System32\findstr.exe /E /I /R /C:"World"
    Echo 4:& Set /P "=%_str%" 0< NUL | %SystemRoot%\System32\findstr.exe /I /R "World$"
    Echo 5:& Set /P "=%_str%" 0< NUL | %SystemRoot%\System32\findstr.exe /I /R "\<World$"
    Echo(
    Echo ERRORLEVEL: %ErrorLevel%
    Pause
    Exit /B
    

    As you can see, I added a couple of extra, options to each of the examples, which for me, are probably more useful for your provided example string. You'll also note that I moved your ampersands, after the test numbers, to show you that you were printing number colon space, not number colon.