Fichier batch: Rechercher si la sous-chaîne est dans la chaîne (pas dans un fichier)

208

Dans un fichier batch, j'ai une chaîne abcdefg. Je veux vérifier si bcdest dans la chaîne.

Malheureusement, il semble que toutes les solutions que je trouve recherchent un fichier pour une sous-chaîne, pas une chaîne pour une sous-chaîne.

Existe-t-il une solution simple à cela?

Ben
la source
5
BTW, c'est généralement soit Windowset cmd ou c'est ms-dos. MSDOS ne fait pas partie de Windows depuis longtemps .
paxdiablo

Réponses:

288

Oui, vous pouvez utiliser des substitutions et vérifier la chaîne d'origine:

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

Le %str1:bcd=%bit remplacera un bcdin str1par une chaîne vide, ce qui le rend différent de l'original.

Si l'original ne contenait pas de bcdchaîne, la version modifiée sera identique.

Le test avec le script suivant le montrera en action:

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

Et les résultats de différentes séries:

c:\testarea> testprog hello

c:\testarea> testprog abcdef
It contains bcd

c:\testarea> testprog bcd
It contains bcd

Quelques notes:

  • La ifdéclaration est la viande de cette solution, tout le reste est du support.
  • L' xavant des deux côtés de l'égalité est de s'assurer que la chaîne bcdfonctionne correctement. Il protège également contre certains caractères de départ "incorrects".
paxdiablo
la source
7
Si vous cherchez à faire un remplacement de chaîne dans une boucle FOR: stackoverflow.com/a/6310580/623622
Czarek Tomczak
60
C'est génial mais j'ai eu du mal à faire fonctionner cela lorsque la valeur de recherche n'était pas une constante (comme bcd) mais plutôt une variable. Après beaucoup de temps, j'ai finalement compris. En supposant que searchVal a été déclaré, "x! Str1:% searchVal% =!" == "x% str1%"
Gary Brunton
7
@Gary, puisque ce n'était pas l'une des exigences de cette question, vous auriez probablement dû poser une question différente, peut-être en vous référant à celle-ci comme référence. Il ne manque pas de gens prêts à aider. En fait, vous devez toujours poser cette question et y répondre vous-même (maintenant que vous l'avez compris) afin qu'elle soit utile aux futurs chercheurs. L'auto-réponse est considérée comme acceptable.
paxdiablo
6
Très bonne solution, mais vous devez mettre entre guillemets ou cela ne fonctionnera pas avec des variables qui ont des espaces dans leurs valeurs, par exemple: sinon "x% str1: bcd =%" == "x% str1%" echo It contient bcd
Helge Klein
4
"'= str1 était inattendu pour le moment"
Berit Larsen
104

Vous pouvez diriger la chaîne source vers findstret vérifier la valeur de ERRORLEVELpour voir si la chaîne de modèle a été trouvée. Une valeur de zéro indique le succès et le modèle a été trouvé. Voici un exemple:

::
: 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
)

Lorsque cela est exécuté dans CMD.EXE, nous obtenons:

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
ghostdog74
la source
"FINDSTR: Argument manquant après / C. Obtenu un - modèle introuvable"
Berit Larsen
47

Je fais habituellement quelque chose comme ça:

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

Exemple:

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

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

Production:

TRUE
FALSE

Je ne sais pas si c'est la meilleure façon.

user839791
la source
J'avais besoin de trouver et de comparer récursivement les noms de fichiers. C'était aussi la seule solution qui fonctionnait pour moi! Super pratique et très simple.
SirJames
24

Pour des raisons de compatibilité et de facilité d'utilisation, il est souvent préférable d'utiliser FIND pour ce faire.

Vous devez également déterminer si vous souhaitez faire correspondre la casse de manière sensible ou insensible.

La méthode avec 78 points (je pense que je faisais référence au message de paxdiablo) ne correspondra qu'à la sensibilité à la casse, vous devez donc cocher séparément chaque variation de cas pour chaque itération possible que vous souhaitez faire correspondre.

(Quelle douleur! À seulement 3 lettres, cela signifie 9 tests différents afin d'accomplir la vérification!)

De plus, il est souvent préférable de faire correspondre la sortie de la commande, une variable dans une boucle ou la valeur d'une variable de pointeur dans votre lot / CMD qui n'est pas aussi simple.

Pour ces raisons, il s'agit d'une méthodologie alternative préférable:

Utilisez: Rechercher [/ I] [/ V] "Caractères à associer"

[/ I] (insensible à la casse) [/ V] (ne doit PAS contenir les caractères)

En ligne simple:

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

Multi-ligne:

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

Comme mentionné, c'est idéal pour les choses qui ne sont pas dans des variables qui permettent également la substitution de chaînes:

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.
Ben Personick
la source
pour les problèmes de respect de la casse, vous pouvez setlocal EnableExtensionsensuite utiliser IF /Ipour effectuer des comparaisons insensibles à la casse.
cychoi
1
Ce n'est pas vraiment une option car il vous faudrait encore isoler les caractères pour une comparaison "IF". SI ne correspondra pas dans les termes "J'aime" car le PO et les solutions particulières auxquelles j'ai répondu recherchent.,
Ben Personick
Salut Ben, Veuillez ne pas vous référer aux autres réponses par le nombre de points qu'elles ont. Cela va probablement changer. Veuillez mettre à jour votre réponse en vous référant à l'autre réponse par le nom de l'auteur de cette réponse, ou par une brève phrase décrivant la technique utilisée dans cette réponse.
phonetagger
Bonjour Phone Tagger, cela aurait été un commentaire utile il y a trois ans lorsque j'ai écrit le message d'origine, mais comme vous le mentionnez, les valeurs des points ont toutes changé. Je ne me souviens plus à quel poste je faisais référence, et je ne ferais pas référence à eux par des valeurs de points aujourd'hui. Merci quand même.
Ben Personick
J'ai regardé autour de moi et je pense que je faisais référence à paxdiablo, j'ai donc modifié le texte pour le montrer.
Ben Personick
10

Si vous détectez une présence, voici la solution la plus simple:

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

Cela fonctionne très bien pour déposer la sortie des commandes Windows dans une variable booléenne. Remplacez simplement l'écho par la commande que vous souhaitez exécuter. Vous pouvez également enchaîner les chaînes de Findstr pour qualifier davantage une instruction à l'aide de canaux. EG pour le contrôle des services (SC.exe)

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

Celui-ci évalue la sortie de SC Query pour les services de mise à jour Windows qui se présente sous la forme d'un texte multiligne, trouve la ligne contenant "état" puis recherche si le mot "en cours d'exécution" apparaît sur cette ligne et définit le niveau d'erreur en conséquence.

byorking
la source
6
Vous avez votre déclaration IF en arrière. En regardant l'original avec abcdefg et vous renversez votre logique. Ça marche. La façon dont vous l'avez, ce n'est pas le cas. SET STRING=abcdefgh SET SUBSTRING=bcd ECHO %STRING% | FINDSTR /C:"%SUBSTRING%" >nul & IF ERRORLEVEL 1 (ECHO CASE FALSE) else (ECHO CASE TRUE)
Leptonator
2
Un +1 est dû même si @Leptonator est correct avec la logique inversée. Il s'agit d'une solution simple et facile à utiliser.
Laryx Decidua
2

J'arrive probablement un peu trop tard avec cette réponse, mais la réponse acceptée ne fonctionne que pour vérifier si une "chaîne codée en dur" fait partie de la chaîne de recherche.

Pour une recherche dynamique, vous devez procéder comme suit:

SET searchString=abcd1234
SET key=cd123

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

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

Remarque: Vous pouvez prendre les deux variables comme arguments.

Andy Sug
la source
1

La meilleure réponse était ici :

set "i=hello " world"
set i|find """" >nul && echo contains || echo not_contains
T.Todua
la source
Dans la question que vous liez en utilisant SET résout un besoin spécifique et unique, il est donc important de mentionner "SET". Cependant, il ne semble rien ajouter à la discussion actuelle, car la méthode de transmission d'une commande à la commande FIND et de test du résultat est déjà fournie
Ben Personick
1
ECHO %String%| FINDSTR /C:"%Substring%" && (Instructions)
Riccardo La Marca
la source
0

Les solutions qui recherchent un fichier pour une sous-chaîne peuvent également rechercher une chaîne , par exemple. findou findstr.
Dans votre cas, la solution simple serait de diriger une chaîne vers la commande au lieu de fournir un nom de fichier, par exemple.

chaîne sensible à la casse:
echo "abcdefg" | find "bcd"

ignorer la casse de la chaîne:
echo "abcdefg" | find /I "bcd"

SI aucune correspondance trouvée, vous obtiendrez une réponse de ligne vierge sur CMD et% ERRORLEVEL% défini sur 1

Zimba
la source