Arquivo em lote: encontre se a substring está na string (não em um arquivo)


208

Em um arquivo em lotes, eu tenho uma string abcdefg. Quero verificar se bcdestá na string.

Infelizmente, parece que todas as soluções que estou encontrando pesquisam um arquivo por uma substring, não uma string para uma substring.

Existe uma solução fácil para isso?


5
BTW, é geralmente quer Windowse cmd ou é ms-dos. O MSDOS não faz parte do Windows há muito tempo.
22411

Respostas:


288

Sim, você pode usar substituições e comparar com a sequência original:

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

O %str1:bcd=%bit substituirá um bcdin str1por uma string vazia, tornando-o diferente do original.

Se o original não contiver uma bcdstring, a versão modificada será idêntica.

Testar com o seguinte script o mostrará em ação:

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

E os resultados de várias execuções:

c:\testarea> testprog hello

c:\testarea> testprog abcdef
It contains bcd

c:\testarea> testprog bcd
It contains bcd

Algumas notas:

  • A ifafirmação é a base desta solução, tudo o resto é material de suporte.
  • O xantes dos dois lados da igualdade é garantir que a string bcdfuncione bem. Também protege contra certos caracteres iniciais "impróprios".

7
Se você está pensando em como fazer a substituição de string em um loop FOR: stackoverflow.com/a/6310580/623622
Czarek Tomczak

60
Isso é ótimo, mas lutei para que isso funcionasse quando o valor da pesquisa não era uma constante (como bcd), mas uma variável. Depois de muito tempo, finalmente descobri. Supondo que searchVal foi declarado, "x! Str1:% searchVal% =!" == "x% str1%"
Gary Brunton

7
@ Gary, já que esse não era um dos requisitos desta pergunta, você provavelmente deveria ter feito uma pergunta diferente, talvez ligando de volta a esta como referência. Não faltam pessoas dispostas a ajudar. Na verdade, você ainda deve fazer essa pergunta e responder a si mesmo (agora que você descobriu) para que seja útil para futuros pesquisadores. A resposta automática é considerada aceitável.
22413

6
Solução muito boa, mas você precisa colocar aspas duplas ou ele não funcionará com variáveis ​​que tenham espaços em seus valores, por exemplo: se não "x% str1: bcd =%" == "x% str1%" echo It contém bcd
Helge Klein

4
"'= str1 foi inesperado neste momento"
Berit Larsen

104

Você pode canalizar a cadeia de origem findstre verificar o valor de ERRORLEVELpara ver se a cadeia de padrão foi encontrada. Um valor zero indica sucesso e o padrão foi encontrado. Aqui está um exemplo:

::
: 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 isso é executado no CMD.EXE, obtemos:

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: Argumento ausente após / C. obteve um padrão não encontrado"
Berit Larsen

47

Eu costumo fazer algo assim:

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

Exemplo:

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

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

Resultado:

TRUE
FALSE

Não sei se é o melhor caminho.


Eu precisava encontrar e comparar recursivamente os nomes dos arquivos. Esta foi a única solução que funcionou para mim também! Super acessível e muito simples.
SirJames

24

Para compatibilidade e facilidade de uso, geralmente é melhor usar o FIND para fazer isso.

Você também deve considerar se deseja corresponder maiúsculas de minúsculas ou maiúsculas de minúsculas.

O método com 78 pontos (acredito que estava me referindo à postagem de paxdiablo) corresponderá apenas a maiúsculas e minúsculas, portanto, você deve colocar uma verificação separada para todas as variações de maiúsculas e minúsculas para cada iteração possível que desejar.

(Que dor! Com apenas 3 letras, isso significa 9 testes diferentes para realizar a verificação!)

Além disso, muitas vezes é preferível combinar a saída do comando, uma variável em um loop ou o valor de uma variável de ponteiro no seu lote / CMD, o que não é tão simples.

Por esses motivos, essa é uma metodologia alternativa preferível:

Uso: Encontre [/ I] [/ V] "Caracteres a Combinar"

[/ I] (não faz distinção entre maiúsculas e minúsculas) [/ V] (NÃO deve conter os caracteres)

Como linha única:

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

Multi-linha:

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

Como mencionado, isso é ótimo para coisas que não estão em variáveis ​​que também permitem a substituição de strings:

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.

para o problema de distinção entre maiúsculas e minúsculas, você pode usá setlocal EnableExtensions-lo IF /Ipara fazer comparações sem distinção entre maiúsculas e minúsculas.
cychoi

1
Essa não é realmente uma opção, porque você ainda precisará isolar os caracteres para uma comparação "SE". SE não irá corresponder em termos "Like" como o OP e soluções particulares I respondeu a está procurando,.
Ben Personick

Oi Ben, por favor, não se refira a outras respostas pelo número de pontos que eles têm. É provável que isso mude. Atualize sua resposta consultando a outra resposta pelo nome do autor da resposta ou por uma breve frase descrevendo a técnica usada nessa resposta.
phonetagger

Oi Phone Tagger, isso teria sido um comentário útil três anos atrás, quando escrevi o post original, no entanto, como você mencionou, os valores dos pontos foram alterados. Não me lembro mais a qual post eu estava me referindo, e não estaria me referindo a eles pelos valores de pontos hoje. Obrigado mesmo assim.
Ben Personick

Olhei em volta e acredito que estava me referindo ao paxdiablo, então alterei o texto para mostrar isso.
quer

10

Se você está detectando presença, aqui está a solução mais fácil:

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

Isso funciona muito bem para soltar a saída dos comandos do Windows em uma variável booleana. Apenas substitua o eco pelo comando que você deseja executar. Você também pode agrupar o Findstr para qualificar ainda mais uma declaração usando pipes. EG para Controle de Serviço (SC.exe)

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

A pessoa avalia a saída do SC Query para serviços de atualização do Windows que sai como um texto de múltiplas linhas, localiza a linha que contém "state" e, em seguida, localiza se a palavra "running" ocorre nessa linha e define o nível de erro de acordo.


6
Você tem sua instrução IF de trás para frente. Olhando para o original com abcdefg, você inverte sua lógica. Funciona. Do jeito que você tem, não tem. SET STRING=abcdefgh SET SUBSTRING=bcd ECHO %STRING% | FINDSTR /C:"%SUBSTRING%" >nul & IF ERRORLEVEL 1 (ECHO CASE FALSE) else (ECHO CASE TRUE)
Leptonator

2
Um +1 é devido mesmo que @Leptonator esteja correto com a lógica invertida. Esta é uma solução simples e fácil de usar.
Laryx Decidua

2

Provavelmente estou chegando tarde demais com esta resposta, mas a resposta aceita funciona apenas para verificar se uma "sequência codificada" faz parte da sequência de pesquisa.

Para pesquisa dinâmica, você teria que fazer o seguinte:

SET searchString=abcd1234
SET key=cd123

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

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

Nota: Você pode usar as duas variáveis ​​como argumentos.


1

Melhor resposta foi aqui :

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

Na pergunta que você vincula usando o SET está resolvendo uma necessidade específica e única, por isso é importante mencionar "SET". No entanto, ele não parece acrescentar nada à discussão atual, como o método de tubulação um comando para o comando Localizar e testar o resultado já é fornecido
Ben Personick


0

As soluções que pesquisam um arquivo por uma substring também podem pesquisar uma string , por exemplo. findou findstr.
No seu caso, a solução fácil mais seria inserir uma string no comando em vez de fornecer um nome de arquivo, por exemplo.

sequência que diferencia maiúsculas de minúsculas:
echo "abcdefg" | find "bcd"

ignorar maiúsculas de minúsculas:
echo "abcdefg" | find /I "bcd"

Se nenhuma correspondência for encontrada, você receberá uma resposta de linha em branco no CMD e% ERRORLEVEL% definido como 1

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.