Пакетный файл: Найти, если подстрока в строке (не в файле)

208

В командном файле у меня есть строка abcdefg. Я хочу проверить, есть ли bcdв строке.

К сожалению, кажется, что все решения, которые я нахожу, ищут файл для подстроки, а не строку для подстроки.

Есть ли простое решение для этого?

Бен
источник
5
Кстати, это обычно либо Windowsи cmd или это ms-dos. MSDOS не является частью Windows , в течение долгого времени.
paxdiablo

Ответы:

288

Да, вы можете использовать подстановки и проверить исходную строку:

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

%str1:bcd=%Немного заменит bcdв str1пустой строке, что делает его отличным от оригинала.

Если в оригинале не было bcdстроки, измененная версия будет идентичной.

Тестирование с помощью следующего скрипта покажет его в действии:

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

И результаты разных заездов:

c:\testarea> testprog hello

c:\testarea> testprog abcdef
It contains bcd

c:\testarea> testprog bcd
It contains bcd

Пара заметок:

  • ifЗаявление мясо этого решения, все остальное является поддержка вещи.
  • xДо двух сторон равенства является обеспечение того , что строка bcdработает нормально. Он также защищает от определенных «неправильных» стартовых персонажей.
paxdiablo
источник
7
Если вы хотите узнать, как выполнить замену строки в цикле FOR: stackoverflow.com/a/6310580/623622
Чарек Томчак,
60
Это замечательно, но я изо всех сил пытался заставить это работать, когда значение поиска не было константой (как bcd), а вместо этого было переменной. Через много времени я наконец понял это. Предполагая, что searchVal был объявлен, "x! Str1:% searchVal% =!" == "x% str1%"
Гари Брунтон
7
@ Гэри, поскольку это не было одним из требований этого вопроса, вам, вероятно, следовало задать другой вопрос, возможно, со ссылкой на этот вопрос в качестве ссылки. Там нет недостатка людей, готовых помочь. На самом деле, вы все равно должны задать этот вопрос и ответить на него самостоятельно (теперь, когда вы это выяснили), чтобы он был полезен для будущих искателей. Автоответчик считается приемлемым.
paxdiablo
6
Очень хорошее решение, но вам нужно заключить в двойные кавычки, иначе оно не будет работать с переменными, у которых есть пробелы в их значениях, например: если не "x% str1: bcd =%" == "x% str1%" echo It содержит bcd
Хельге Кляйн
4
"'= str1 был неожиданным в это время"
Берит Ларсен
104

Вы можете передать исходную строку findstrи проверить значение, ERRORLEVELчтобы увидеть, была ли найдена строка шаблона. Нулевое значение указывает на успех, и шаблон был найден. Вот пример:

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

Когда это выполняется в CMD.EXE, мы получаем:

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
источник
«FINDSTR: Аргумент отсутствует после / C. Получил один - шаблон не найден»
Берит Ларсен
47

Я обычно делаю что-то вроде этого:

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

Пример:

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

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

Вывод:

TRUE
FALSE

Я не знаю, если это лучший способ.

user839791
источник
Мне нужно было рекурсивно найти и сравнить имена файлов. Это было единственное решение, которое сработало и для меня! Супер удобно и очень просто.
SirJames
24

Для совместимости и простоты использования часто лучше использовать FIND для этого.

Вы также должны подумать, хотите ли вы сопоставить регистр с учетом регистра или без учета регистра.

Метод с 78 баллами (я полагаю, что я имел в виду пост Паксдиабло) будет сопоставляться только с учетом регистра, поэтому вы должны поставить отдельную проверку для каждого варианта регистра для каждой возможной итерации, которую вы можете захотеть сопоставить.

(Какая боль! Всего 3 буквы, что означает 9 различных тестов для выполнения проверки!)

Кроме того, во многих случаях предпочтительно сопоставлять выходные данные команды, переменную в цикле или значение переменной-указателя в вашем пакете / CMD, что не так просто.

По этим причинам это предпочтительная альтернативная методология:

Использование: Найти [/ I] [/ V] «Персонажи для сопоставления»

[/ I] (без учета регистра) [/ V] (НЕ ДОЛЖНО содержать символы)

Как одиночная линия:

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

Многоканальный:

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

Как уже упоминалось, это отлично подходит для вещей, которые не входят в переменные, которые также допускают подстановку строк:

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.
Бен Персоник
источник
для учета чувствительности к регистру вы можете использовать setlocal EnableExtensionsзатем IF /Iдля сравнения без учета регистра.
cychoi
1
Это на самом деле не вариант, потому что вам все равно нужно изолировать символы для сравнения «IF». ЕСЛИ не будет соответствовать условиям «Мне нравится», так как ищут ОП и конкретные решения, на которые я отвечал.,
Бен Персоник,
Привет Бен, пожалуйста, не обращайтесь к другим ответам по количеству баллов, которые они имеют. Это может измениться. Пожалуйста, обновите свой ответ, ссылаясь на другой ответ, указав имя автора этого ответа или краткую фразу, описывающую методику, использованную в этом ответе.
телефонный звонок
Привет, Phone Tagger, это был бы полезный комментарий три года назад, когда я писал оригинальное сообщение, однако, как вы упомянули, значения баллов все изменились. Я больше не помню, на какой пост я ссылался, и я бы не стал ссылаться на них сегодня по баллам. Спасибо, в любом случае.
Бен
Я оглянулся и, кажется, имел в виду paxdiablo, поэтому я изменил текст, чтобы показать это.
Бен
10

Если вы обнаруживаете присутствие, вот самое простое решение:

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

Это прекрасно работает для сброса вывода команд Windows в логическую переменную. Просто замените эхо командой, которую хотите запустить. Вы также можете связать Findstr вместе, чтобы дополнительно квалифицировать оператор, используя каналы. EG для управления службами (SC.exe)

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

Тот оценивает выходные данные SC Query для служб обновления Windows, которые появляются в виде многострочного текста, находит строку, содержащую «состояние», затем находит, встречается ли слово «выполняется» в этой строке, и соответственно устанавливает уровень ошибки.

byorking
источник
6
У вас есть обратное выражение IF. Глядя на оригинал с помощью abcdefg, вы переворачиваете логику. Оно работает. То, как у вас есть, это не так. SET STRING=abcdefgh SET SUBSTRING=bcd ECHO %STRING% | FINDSTR /C:"%SUBSTRING%" >nul & IF ERRORLEVEL 1 (ECHO CASE FALSE) else (ECHO CASE TRUE)
Лептонатор
2
+1 должен получиться, даже если @Leptonator корректен с инвертированной логикой. Это простое и удобное решение.
Ларикс Децидуа
2

Возможно, я слишком поздно приду с этим ответом, но принятый ответ работает только для проверки, является ли «жестко закодированная строка» частью строки поиска.

Для динамического поиска вы должны сделать это:

SET searchString=abcd1234
SET key=cd123

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

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

Примечание: вы можете взять две переменные в качестве аргументов.

Энди Суг
источник
1

Лучший ответ был здесь :

set "i=hello " world"
set i|find """" >nul && echo contains || echo not_contains
T.Todua
источник
В вопросе, который вы связываете с помощью SET, решается конкретная и уникальная потребность, поэтому важно упомянуть «SET». Однако, похоже, что это ничего не добавляет к текущему обсуждению, так как метод передачи команды в команду FIND и проверки результата уже предоставлен
Ben Personick
1
ECHO %String%| FINDSTR /C:"%Substring%" && (Instructions)
Риккардо Ла Марка
источник
0

Решения, которые ищут файл для подстроки, могут также искать строку , например. findили findstr.
В вашем случае простое решение было бы передать строку в команду вместо указания имени файла, например.

чувствительная к регистру строка:
echo "abcdefg" | find "bcd"

игнорировать регистр строки:
echo "abcdefg" | find /I "bcd"

Если совпадение не найдено, вы получите пустой ответ на CMD, и% ERRORLEVEL% будет установлен в 1

Zimba
источник