Regular expressions in findstr

2019-01-17 10:20发布

I'm doing a little string validation with findstr and its /r flag to allow for regular expressions. In particular I'd like to validate integers.

The regex

^[0-9][0-9]*$

worked fine for non-negative numbers but since I now support negative numbers as well I tried

^([1-9][0-9]*|0|-[1-9][0-9]*)$

for either positive or negative integers or zero.

The regex works fine theoretically. I tested it in PowerShell and it matches what I want. However, with

findstr /r /c:"^([1-9][0-9]*|0|-[1-9][0-9]*)$"

it doesn't.

While I know that findstr doesn't have the most advanced regex support (even below Notepad++ which is probably quite an achievement), I would have expected such simple expressions to work.

Any ideas what I'm doing wrong here?

5条回答
走好不送
2楼-- · 2019-01-17 10:39

I realize this is a really old post but thought it may come up in the future so I quickly hacked out a little more advanced batch solution. Normally I would just use powershell, python, ruby or vbs. It's a lot more challenging in a batch language but why not. :-P


        @ECHO OFF
        REM The _Ignore_ variable ignores text turning search if needed
        SET _Ignore_=Ignore_something_if_you_need
        REM Set the _Debug_ variable if you want to see all the output.
        SET _Debug_=
        REM Save this as a batch file and test it by passing

        REM Usage: 
        REM Example 1:
        REM IsItTextOrIsItANumberRegxExample.bat 123
        REM Results:Found Number:"123"

        REM Example 2:
        REM IsItTextOrIsItANumberRegxExample.bat Michael123
        REM Results:Found Number:"Michael123"

        CALL:--CheckString %1
        GOTO :Done

        :--CheckString
        SET __CheckString__=%~1
        SET _RETURN_LETTERS_=""
        SET _RETURN_NUMBERS_=""
        REM Using EnableDelayedExpansion to more completely Expand the for loop results and pack in the results. 
        SETLOCAL ENABLEDELAYEDEXPANSION
        FOR /F "tokens=1*" %%A IN ('Echo %__CheckString__%^|findstr /r "^[1-9][0-9]*$ ^-[1-9][0-9]*$ ^0$"') DO (
            IF DEFINED _Debug_ ECHO Debug:%%A
            If %ERRORLEVEL% EQU 0 (
                IF NOT "%%A"=="%_Ignore_%" (
                    IF NOT "%%A"==" " (
                        SET __ReturnNumber__=%%A
                        SET __ReturnNumber__=!__ReturnNumber__: =!
                    )
                )
            )
        )
        ENDLOCAL && SET _RETURN_NUMBERS_=%__ReturnNumber__%
        REM Note: SETLOCAL is used twice because sometimes variable output will add spaces when using two similar for loops.
        SETLOCAL ENABLEDELAYEDEXPANSION
        FOR /F "tokens=1*" %%A IN ('Echo %__CheckString__%^|findstr /r "^[a-z][A-Z]*[0-9]*"') DO (
            IF DEFINED _Debug_ ECHO DEBUG:%%A
            If %ERRORLEVEL% EQU 0 (
                IF NOT "%%A"=="%_Ignore_%" (
                    IF NOT "%%A"==" " (
                        SET __ReturnLetters__=%%A
                    )
                )
            )
        )
        ENDLOCAL && SET _RETURN_LETTERS_=%__ReturnLetters__%
        GOTO:EOF

        :Done
        IF DEFINED _RETURN_NUMBERS_ ECHO Found Number:"%_RETURN_NUMBERS_%"
        IF DEFINED _RETURN_LETTERS_ ECHO Found Letters:"%_RETURN_LETTERS_%"

        REM Cleanup:
        SET _Ignore_=
        SET _RETURN_NUMBERS_=
        SET _RETURN_LETTERS_=
        SET _Ignore_=
        SET _Debug_=
查看更多
Viruses.
3楼-- · 2019-01-17 10:45

Or if you can, download grep for windows.. Many more features than findstr provides.

查看更多
Luminary・发光体
4楼-- · 2019-01-17 10:52

Argh, I should have read the documentation better. findstr apparently doesn't support alternations (|).

So I'm probably back to multiple invocations or replacing the whole thing with a custom parser eventually.

This is what I do for now:

set ERROR=1
rem Test for zero
echo %1|findstr /r /c:"^0$">nul 2>&1
if not errorlevel 1 set ERROR=
rem Test for positive numbers
echo %1|findstr /r /c:"^[1-9][0-9]*$">nul 2>&1
if not errorlevel 1 set ERROR=
rem Test for negative numbers
echo %1|findstr /r /c:"^-[1-9][0-9]*$">nul 2>&1
if not errorlevel 1 set ERROR=
查看更多
兄弟一词,经得起流年.
5楼-- · 2019-01-17 11:02

This works for me:

findstr /r "^[1-9][0-9]*$ ^-[1-9][0-9]*$ ^0$"

If you don't use the /c option, the <Strings> argument is treated as a space-separated list of search strings, which makes the space a sort of crude replacement for the | construct. (As long as your regexes don't contain spaces, that is.)

查看更多
姐就是有狂的资本
6楼-- · 2019-01-17 11:03

A simpler regex that achieves the same thing is possible, just add an optional minus to the start of your original expression:

^-?[0-9][0-9]*$
查看更多
登录 后发表回答