File batch: trova se la sottostringa è nella stringa (non in un file)


208

In un file batch, ho una stringa abcdefg. Voglio verificare se bcdè nella stringa.

Sfortunatamente sembra che tutte le soluzioni che sto trovando cerchino un file per una sottostringa, non una stringa per una sottostringa.

C'è una soluzione semplice per questo?


5
A proposito, di solito è o Windowse cmd o è ms-dos. MSDOS non fa parte di Windows da molto tempo.
paxdiablo,

Risposte:


288

Sì, è possibile utilizzare le sostituzioni e verificare la stringa originale:

if not x%str1:bcd=%==x%str1% echo It contains bcd

Il %str1:bcd=%bit sostituirà un bcdin str1con una stringa vuota, rendendolo diverso dall'originale.

Se l'originale non conteneva una bcdstringa, la versione modificata sarà identica.

Il test con il seguente script lo mostrerà in azione:

@setlocal enableextensions enabledelayedexpansion
@echo off
set str1=%1
if not x%str1:bcd=%==x%str1% echo It contains bcd
endlocal

E i risultati di varie corse:

c:\testarea> testprog hello

c:\testarea> testprog abcdef
It contains bcd

c:\testarea> testprog bcd
It contains bcd

Un paio di note:

  • La ifdichiarazione è la carne di questa soluzione, tutto il resto è roba di supporto.
  • La parte xanteriore dei due lati dell'uguaglianza è assicurarsi che la stringa bcdfunzioni correttamente. Protegge anche da alcuni personaggi iniziali "impropri".

7
Se siete alla ricerca su come fare la sostituzione di stringa in un ciclo FOR: stackoverflow.com/a/6310580/623622
Czarek Tomczak

60
Questo è fantastico ma ho faticato a farlo funzionare quando il valore di ricerca non era una costante (come bcd) ma era invece una variabile. Dopo molto tempo ho finalmente capito. Supponendo che searchVal sia stato dichiarato, "x! Str1:% searchVal% =!" == "x% str1%"
Gary Brunton,

7
@Gary, dato che non era uno dei requisiti di questa domanda, probabilmente avresti dovuto porre una domanda diversa, forse ricollegandola a questa come riferimento. Non mancano le persone disposte ad aiutare. In effetti, devi ancora porre questa domanda e rispondere tu stesso (ora che l'hai capito) in modo che sia utile per i futuri ricercatori. L'auto-risposta è considerata accettabile.
paxdiablo,

6
Ottima soluzione, ma è necessario racchiuderla tra virgolette doppie o non funzionerà con variabili che hanno spazi nei loro valori, ad es .: in caso contrario "x% str1: bcd =%" == "x% str1%" echo contiene bcd
Helge Klein il

4
"'= str1 era inaspettato in questo momento"
Berit Larsen

104

È possibile reindirizzare la stringa di origine findstre verificare il valore di ERRORLEVELper vedere se la stringa del modello è stata trovata. Un valore pari a zero indica il successo e il modello è stato trovato. Ecco un esempio:

::
: Y.CMD - Test if pattern in string
: P1 - the pattern
: P2 - the string to check
::
@echo off

echo.%2 | findstr /C:"%1" 1>nul

if errorlevel 1 (
  echo. got one - pattern not found
) ELSE (
  echo. got zero - found pattern
)

Quando questo viene eseguito in CMD.EXE, otteniamo:

C:\DemoDev>y pqrs "abc def pqr 123"
 got one - pattern not found

C:\DemoDev>y pqr "abc def pqr 123" 
 got zero - found pattern

"FINDSTR: Argomento mancante dopo / C. Ottenuto uno - modello non trovato"
Berit Larsen

47

Di solito faccio qualcosa del genere:

Echo.%1 | findstr /C:"%2">nul && (
    REM TRUE
) || (
    REM FALSE
)

Esempio:

Echo.Hello world | findstr /C:"world">nul && (
    Echo.TRUE
) || (
    Echo.FALSE
)

Echo.Hello world | findstr /C:"World">nul && (Echo.TRUE) || (Echo.FALSE)

Produzione:

TRUE
FALSE

Non so se questo è il modo migliore.


Avevo bisogno di trovare ricorsivamente e confrontare i nomi dei file. Questa è stata l'unica soluzione che ha funzionato anche per me! Super pratico e molto semplice.
SirJames

24

Per compatibilità e facilità d'uso è spesso meglio usare FIND per farlo.

È inoltre necessario considerare se si desidera abbinare il caso in modo sensibile o caso insensibile.

Il metodo con 78 punti (credo che mi riferissi al post di paxdiablo) corrisponderà solo a Case Sensitively, quindi devi mettere un controllo separato per ogni variazione del caso per ogni possibile iterazione che potresti voler abbinare.

(Che dolore! Solo 3 lettere significa 9 test diversi per completare il controllo!)

Inoltre, molte volte è preferibile abbinare l'output del comando, una variabile in un ciclo o il valore di una variabile puntatore nel batch / CMD che non è così semplice.

Per questi motivi questa è una metodologia alternativa preferibile:

Usa: Trova [/ I] [/ V] "Personaggi da abbinare"

[/ I] (senza distinzione tra maiuscole e minuscole) [/ V] (NON deve contenere i caratteri)

Come linea singola:

ECHO.%Variable% | FIND /I "ABC">Nul && ( Echo.Found "ABC" ) || ( Echo.Did not find "ABC" )

Multi-line:

ECHO.%Variable%| FIND /I "ABC">Nul && ( 
  Echo.Found "ABC"
) || (
  Echo.Did not find "ABC"
)

Come accennato, questo è ottimo per le cose che non sono in variabili che consentono anche la sostituzione di stringhe:

FOR %A IN (
  "Some long string with Spaces does not contain the expected string"
  oihu AljB
  lojkAbCk
  Something_Else
 "Going to evaluate this entire string for ABC as well!"
) DO (
  ECHO.%~A| FIND /I "ABC">Nul && (
    Echo.Found "ABC" in "%A"
  ) || ( Echo.Did not find "ABC" )
)

Output From a command:

    NLTest | FIND /I "ABC">Nul && ( Echo.Found "ABC" ) || ( Echo.Did not find "ABC" )

As you can see this is the superior way to handle the check for multiple reasons.

per problemi di distinzione tra maiuscole e minuscole, è possibile utilizzare setlocal EnableExtensionsquindi IF /Iper eseguire confronti senza distinzione tra maiuscole e minuscole.
cychoi,

1
Questa non è davvero un'opzione perché sarebbe comunque necessario isolare i caratteri per un confronto "IF". Se i termini "mi piace" non coincidono con quelli che l'OP e le soluzioni particolari a cui ho risposto stanno cercando.,
Ben Personick

Ciao Ben, per favore non fare riferimento ad altre risposte per il numero di punti che hanno. È probabile che cambi. Aggiorna la tua risposta facendo riferimento all'altra risposta con il nome dell'autore di quella risposta o con una breve frase che descriva la tecnica utilizzata in quella risposta.
Fonagger

Ciao telefono Tagger, sarebbe stato un commento utile tre anni fa quando ho scritto il post originale, tuttavia, come hai detto, i valori dei punti sono tutti cambiati. Non ricordo più a quale post mi riferivo e oggi non mi riferirei a loro con i valori dei punti. Grazie comunque.
Ben Personick,

Mi sono guardato intorno e credo di riferirmi a paxdiablo, quindi ho modificato il testo per dimostrarlo.
Ben Personick,

10

Se stai rilevando la presenza, ecco la soluzione più semplice:

SET STRING=F00BAH
SET SUBSTRING=F00
ECHO %STRING% | FINDSTR /C:"%SUBSTRING%" >nul & IF ERRORLEVEL 1 (ECHO CASE TRUE) else (ECHO CASE FALSE)

Funziona perfettamente per eliminare l'output dei comandi di Windows in una variabile booleana. Basta sostituire l'eco con il comando che si desidera eseguire. Puoi anche mettere insieme le stringhe di Findstr per qualificare ulteriormente un'istruzione usando le pipe. EG per Service Control (SC.exe)

SC QUERY WUAUSERV | findstr /C:"STATE" | FINDSTR /C:"RUNNING" & IF ERRORLEVEL 1 (ECHO case True) else (ECHO CASE FALSE)

Quello valuta l'output di SC Query per i servizi di aggiornamento di Windows che esce come un testo multilinea, trova la riga contenente "stato", quindi trova se la parola "in esecuzione" appare su quella linea e imposta il livello di errore di conseguenza.


6
Hai la tua dichiarazione IF all'indietro .. Guardando l'originale con abcdefg e capovolgi la tua logica. Funziona. Il modo in cui lo hai, non lo fa. SET STRING=abcdefgh SET SUBSTRING=bcd ECHO %STRING% | FINDSTR /C:"%SUBSTRING%" >nul & IF ERRORLEVEL 1 (ECHO CASE FALSE) else (ECHO CASE TRUE)
Leptonator,

2
È necessario un +1 anche se @Leptonator è corretto con la logica invertita. Questa è una soluzione semplice e facile da usare.
Laryx Decidua,

2

Probabilmente sto arrivando un po 'troppo tardi con questa risposta, ma la risposta accettata funziona solo per verificare se una "stringa codificata" fa parte della stringa di ricerca.

Per la ricerca dinamica, dovresti fare questo:

SET searchString=abcd1234
SET key=cd123

CALL SET keyRemoved=%%searchString:%key%=%%

IF NOT "x%keyRemoved%"=="x%searchString%" (
    ECHO Contains.
)

Nota: è possibile prendere le due variabili come argomenti.


1

La risposta migliore era qui :

set "i=hello " world"
set i|find """" >nul && echo contains || echo not_contains

Nella domanda che colleghi usando SET sta risolvendo un'esigenza specifica e unica, quindi è importante menzionare "SET". Tuttavia, non sembra aggiungere nulla alla discussione corrente, poiché il metodo di reindirizzare un comando al comando FIND e testare il risultato è già fornito
Ben Personick


0

Le soluzioni che cercano un file per una sottostringa possono anche cercare una stringa , ad es. findofindstr .
Nel tuo caso, la soluzione semplice sarebbe quella di inserire una stringa nel comando invece di fornire un nome file ad es.

stringa sensibile al maiuscolo / minuscolo:
echo "abcdefg" | find "bcd"

ignora il caso della stringa:
echo "abcdefg" | find /I "bcd"

Se non viene trovata alcuna corrispondenza, otterrai una risposta in linea vuota su CMD e% ERRORLEVEL% impostato su 1

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.