Archivo por lotes: busque si la subcadena está en cadena (no en un archivo)

208

En un archivo por lotes, tengo una cadena abcdefg. Quiero verificar si bcdestá en la cadena.

Desafortunadamente, parece que todas las soluciones que encuentro buscan un archivo para una subcadena, no una cadena para una subcadena.

¿Hay una solución fácil para esto?

Ben
fuente
55
Por cierto, es por lo general bien Windowsy cmd o es ms-dos. MSDOS no ha sido parte de Windows durante mucho tiempo.
paxdiablo

Respuestas:

288

Sí, puede usar sustituciones y verificar con la cadena original:

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

La %str1:bcd=%bits reemplazará a una bcdde str1con una cadena vacía, por lo que es diferente de la original.

Si el original no contiene una bcdcadena, la versión modificada será idéntica.

La prueba con el siguiente script lo mostrará en acción:

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

Y los resultados de varias ejecuciones:

c:\testarea> testprog hello

c:\testarea> testprog abcdef
It contains bcd

c:\testarea> testprog bcd
It contains bcd

Un par de notas:

  • La ifdeclaración es la carne de esta solución, todo lo demás es material de soporte.
  • Lo xanterior a los dos lados de la igualdad es asegurar que la cadena bcdfuncione bien. También protege contra ciertos caracteres iniciales "inapropiados".
paxdiablo
fuente
77
Si está buscando cómo hacer un reemplazo de cadena en un bucle FOR: stackoverflow.com/a/6310580/623622
Czarek Tomczak
6060
Esto es genial, pero luché para que esto funcionara cuando el valor de búsqueda no era una constante (como bcd) sino una variable. Después de mucho tiempo, finalmente lo descubrí. Suponiendo que se haya declarado searchVal, "x! Str1:% searchVal% =!" == "x% str1%"
Gary Brunton
77
@Gary, dado que ese no era uno de los requisitos de esta pregunta, probablemente debiste haber hecho una pregunta diferente, tal vez vinculando a esta como referencia. No hay escasez de personas dispuestas a ayudar. De hecho, aún debe hacer esa pregunta y responderla usted mismo (ahora que lo ha resuelto) para que sea útil para los futuros buscadores. La respuesta automática se considera aceptable.
paxdiablo
66
Muy buena solución, pero necesita encerrar entre comillas dobles o no funcionará con variables que tengan espacios en sus valores, por ejemplo: si no "x% str1: bcd =%" == "x% str1%" echo It contiene bcd
Helge Klein
44
"'= str1 fue inesperado en este momento"
Berit Larsen
104

Puede canalizar la cadena de origen findstry verificar el valor de ERRORLEVELpara ver si se encontró la cadena de patrón. Un valor de cero indica éxito y se encontró el patrón. Aquí hay un ejemplo:

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

Cuando esto se ejecuta en CMD.EXE, obtenemos:

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
fuente
"FINDSTR: Argumento perdido después de / C. Obtuve uno - patrón no encontrado"
Berit Larsen
47

Usualmente hago algo como esto:

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

Ejemplo:

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

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

Salida:

TRUE
FALSE

No sé si esta es la mejor manera.

user839791
fuente
Necesitaba encontrar y comparar recursivamente nombres de archivos. ¡Esta fue la única solución que también funcionó para mí! Super manejable y muy simple.
SirJames el
24

Por compatibilidad y facilidad de uso, a menudo es mejor usar FIND para hacer esto.

También debe considerar si desea hacer coincidir mayúsculas y minúsculas o mayúsculas y minúsculas.

El método con 78 puntos (creo que me refería a la publicación de paxdiablo) solo coincidirá con mayúsculas y minúsculas, por lo que debe marcar por separado cada variación de caso para cada iteración posible que desee que coincida.

(¡Qué pena! ¡Con solo 3 letras, eso significa 9 pruebas diferentes para realizar la verificación!)

Además, muchas veces es preferible hacer coincidir la salida del comando, una variable en un bucle o el valor de una variable de puntero en su lote / CMD que no es tan sencillo.

Por estas razones, esta es una metodología alternativa preferible:

Uso: Buscar [/ I] [/ V] "Personajes para unir"

[/ I] (mayúsculas y minúsculas) [/ V] (NO debe contener los caracteres)

Como línea única:

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

Multilínea:

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

Como se mencionó, esto es ideal para cosas que no están en variables que también permiten la sustitución de cadenas:

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
fuente
para la emisión de mayúsculas y minúsculas, puede utilizar setlocal EnableExtensionsa continuación, IF /Ihacer comparaciones mayúsculas y minúsculas.
cychoi
1
Esa no es realmente una opción porque aún necesitaría aislar los caracteres para una comparación "SI". IF no coincidirá en los términos "Me gusta" como el OP y las soluciones particulares que respondí están buscando.,
Ben Personick
Hola Ben, por favor no te refieras a otras respuestas por la cantidad de puntos que tienen. Es probable que eso cambie. Actualice su respuesta refiriéndose a la otra respuesta por el nombre del autor de esa respuesta, o por una breve frase que describa la técnica utilizada en esa respuesta.
phonetagger
Hola Phone Tagger, eso habría sido un comentario útil hace tres años cuando escribí la publicación original, sin embargo, como mencionas, los valores de los puntos han cambiado. Ya no recuerdo a qué publicación me refería, y hoy no me referiría a ellos por valores de puntos. Gracias de cualquier manera.
Ben Personick
Miré a mi alrededor y creo que me refería a paxdiablo, así que modifiqué el texto para mostrarlo.
Ben Personick
10

Si está detectando presencia, esta es la solución más fácil:

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

Esto funciona muy bien para colocar la salida de los comandos de Windows en una variable booleana. Simplemente reemplace el eco con el comando que desea ejecutar. También puede encadenar Findstr's para calificar aún más una declaración utilizando tuberías. EG para Control de Servicio (SC.exe)

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

Ese evalúa la salida de SC Query para los servicios de actualización de Windows que sale como un texto multilínea, encuentra la línea que contiene "estado" y luego encuentra si la palabra "en ejecución" aparece en esa línea, y establece el nivel de error en consecuencia.

byorking
fuente
66
Tienes tu declaración IF al revés. Mirando el original con abcdefg y cambias tu lógica. Funciona. La forma en que lo tienes, no lo hace. SET STRING=abcdefgh SET SUBSTRING=bcd ECHO %STRING% | FINDSTR /C:"%SUBSTRING%" >nul & IF ERRORLEVEL 1 (ECHO CASE FALSE) else (ECHO CASE TRUE)
Leptonator
2
A +1 se debe aunque @Leptonator es correcto con la lógica invertida. Esta es una solución simple y fácil de usar.
Laryx Decidua
2

Probablemente llegue demasiado tarde con esta respuesta, pero la respuesta aceptada solo funciona para verificar si una "cadena codificada" es parte de la cadena de búsqueda.

Para la búsqueda dinámica, tendría que hacer esto:

SET searchString=abcd1234
SET key=cd123

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

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

Nota: Puede tomar las dos variables como argumentos.

Andy Sug
fuente
1

Mejor respuesta estaba aquí :

set "i=hello " world"
set i|find """" >nul && echo contains || echo not_contains
T.Todua
fuente
En la pregunta que vincula usando SET está resolviendo una necesidad específica y única, por lo que es importante mencionar "SET". Sin embargo, no parece agregar nada a la discusión actual, ya que el método de canalizar un comando al comando FIND y probar el resultado ya está disponible
Ben Personick
1
ECHO %String%| FINDSTR /C:"%Substring%" && (Instructions)
Riccardo La Marca
fuente
0

Las soluciones que buscan un archivo para una subcadena también pueden buscar una cadena , por ejemplo. findo findstr.
En tu caso, la solución fácil sería canalizar una cadena en el comando en lugar de proporcionar un nombre de archivo, por ejemplo.

cadena sensible a mayúsculas y minúsculas:
echo "abcdefg" | find "bcd"

ignorar caso de cadena:
echo "abcdefg" | find /I "bcd"

SI no se encuentra ninguna coincidencia, obtendrá una respuesta de línea en blanco en CMD y% ERRORLEVEL% establecido en 1

Zimba
fuente