2010-04-10 54 views
26

Estoy haciendo una pequeña validación de cadena con findstr y su indicador /r para permitir expresiones regulares. En particular, me gustaría validar enteros.Expresiones regulares en findstr

La expresión regular

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

funcionó bien para los números no negativos, pero ya que ahora son compatibles con los números negativos, así que intentaron

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

, ya sea para los enteros positivos o negativos o cero.

La expresión regular funciona bien teóricamente. Lo probé en PowerShell y coincide con lo que quiero. Sin embargo, con

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

no.

Aunque sé que findstr no tiene el soporte de expresiones regulares más avanzado (incluso debajo de Notepad ++, que probablemente sea todo un logro), hubiera esperado que tales expresiones simples funcionaran.

¿Alguna idea de lo que estoy haciendo mal aquí?

+0

Nota para el editor: El * Windows * etiqueta es un poco superflua, ya que 'findstr' sólo existe allí ... – Joey

+12

Rossel: Tags están ahí para ayudar a encontrar cosas. Una redundancia moderada no duele en este caso. – jfs

+0

Nunca buscaría una etiqueta tan abarrotada como * windows * ;-), pero si crees que ayudará ... – Joey

Respuesta

37

Esto funciona para mí:

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

Si no utiliza la opción /c, el argumento <Strings> es tratado como un lista separada por espacios de cadenas de búsqueda, lo que hace que el espacio en una especie de reemplazo crudo para la construcción |. (Siempre y cuando sus expresiones regulares no contienen espacios, es decir.)

+0

Aah, cierto que eres. Esa que olvidé. Sí, los espacios en el RE serían malos, pero eso no será un problema aquí. – Joey

+1

Soy reacio a votar como un abuso de la sintaxis de expresiones regulares, pero resolvió mi problema, ¡gracias! :-pag – yoyo

8

Argh, debería haber leído the documentation mejor. findstr aparentemente no es compatible con las alternancias (|).

Así que probablemente regrese a múltiples invocaciones o reemplazando todo con un analizador personalizado eventualmente.

Esto es lo que hago por ahora:

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= 
+0

Según lo sugerido por Alan Moore, si su cadena de búsqueda no contiene espacios, entonces el carácter de espacio funcionará como | en expresiones regulares 'regulares' :) si todo lo que está haciendo es buscar dar salida a cualquier línea que contenga una lista de cadenas que tenga. – smartexpert

+0

@smartexpert: Puede haber notado que la respuesta de Alan es la aceptada. – Joey

2

O si se puede, descarga grep for windows.. Muchas más características que findstr proporciona.

+0

No hay opción aquí. Esta es una biblioteca bignum de lote puro. Buscaré un analizador apropiado cuando termine con la aritmética básica. Esto también será mucho mejor para los mensajes de error adecuados. Por ahora, múltiples invocaciones de 'findstr' deberían ser suficientes. Además, si fuera solo por características, simplemente llamaría a PowerShell. Mucho más fácil, mucho más poderoso. – Joey

+0

Estoy fascinado de saber que alguien quería bignums en un archivo de bat. –

0

Un simple regex que logra la misma cosa es posible, sólo tiene que añadir un signo menos opcional al inicio de su expresión original:

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

Me doy cuenta de que esta es una publicación muy antigua, pero pensé que podría surgir en el futuro, así que rápidamente arreglé una solución de lotes más avanzada. Normalmente solo usaría powershell, python, ruby ​​o vbs. Es mucho más desafiante en un lenguaje por lotes, pero ¿por qué no? :-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_=