2010-04-10 25 views
26

Sto eseguendo una piccola stringa di convalida con findstr e il suo flag /r per consentire espressioni regolari. In particolare mi piacerebbe convalidare interi.Espressioni regolari nel findstr

La regex

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

funzionava bene per i numeri non negativi, ma dato che ora sostengo numeri negativi così ho provato

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

sia per numeri interi positivi o negativi o zero.

Il regex funziona bene teoricamente. L'ho provato in PowerShell e corrisponde a quello che voglio. Tuttavia, con

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

no.

Mentre so che findstr non ha il supporto di regex più avanzato (anche sotto Notepad ++ che è probabilmente un risultato), mi sarei aspettato che tali espressioni semplici funzionassero.

Qualche idea su cosa sto facendo male qui?

+0

Nota per l'editor: il * Windows * tag è un po 'superfluo, visto che 'findstr' esiste solo lì ... – Joey

+12

Rossel: I tag sono lì per aiutare a trovare le cose. In questo caso una moderata ridondanza non fa male. – jfs

+0

Non avrei mai cercato un tag sovraffollato come * windows * ;-) ma se pensi che ti possa aiutare ... – Joey

risposta

37

questo funziona per me:

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

Se non si utilizza l'opzione /c, l'argomento <Strings> viene trattato come uno spazio separato da lista delle stringhe di ricerca, il che rende lo spazio una sorta di sostituzione grezza per il costrutto |. (Fino a quando le vostre espressioni regolari non contengono spazi, che è.)

+0

Aah, giusto sei. Quello che ho dimenticato. Sì, gli spazi nella RE sarebbero cattivi, ma non sarà un problema qui. – Joey

+1

Sono riluttante a votare un tale abuso di sintassi delle espressioni regolari, ma hai risolto il mio problema, grazie! :-p – yoyo

8

Argh, avrei dovuto leggere meglio the documentation. findstr a quanto pare non supporta le alternazioni (|).

Quindi probabilmente tornerò a più invocazioni o alla fine sostituirò il tutto con un parser personalizzato.

Questo è quello che faccio per ora:

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

Come suggerito da Alan Moore, se la stringa di ricerca non contiene spazi, il carattere dello spazio funzionerà come | in espressioni regolari 'regolari' :) se tutto quello che stai facendo è cercare di generare una riga contenente un elenco di stringhe che hai. – smartexpert

+0

@smartexpert: potresti aver notato che la risposta di Alan è accettata. – Joey

2

Oppure, se è possibile, scaricare grep for windows.. Sono disponibili molte più funzioni di findstr.

+0

Nessuna opzione qui. Questa è una libreria bignum batch pura. Vado per un parser corretto quando ho finito con l'aritmetica di base. Questo sarà anche molto meglio per i messaggi di errore corretti. Per ora dovrebbero essere sufficienti più chiamate 'findstr'. Inoltre, se fosse solo per funzionalità che chiamerei PowerShell. Molto più facile, molto più potente. – Joey

+0

Sono affascinato dal fatto che so che chiunque vorrebbe bignums in un file bat. –

0

Un semplice regex che raggiunge la stessa cosa è possibile, basta aggiungere un meno opzionale per l'inizio della vostra espressione originale:

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

Mi rendo conto che questo è un post davvero vecchio, ma ho pensato che potrebbe venire in futuro, così ho rapidamente eliminato una soluzione batch più avanzata. Normalmente userei solo powershell, python, ruby ​​o vbs. È molto più impegnativo in un linguaggio batch, ma perché 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_=