Пакетний файл: Знайдіть, чи є підрядковий рядок (не у файлі)


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працює нормально. Він також захищає від певних "неправильних" стартових символів.

7
Якщо ви шукаєте, як зробити заміну рядків у циклі FOR: stackoverflow.com/a/6310580/623622
Czarek Tomczak

60
Це чудово, але я намагався змусити це працювати, коли значення пошуку не було постійним (наприклад, bcd), а замість цього є змінною. Через багато часу я нарешті зрозумів це. Якщо припустити, що пошук SearchVal оголошено, "x! Str1:% searchVal% =!" == "x% str1%"
Gary Brunton

7
@Gary, оскільки це не було однією з вимог цього питання, ви, ймовірно, мали б задати інше питання, можливо, посилаючись на це як посилання. Не бракує бажаючих допомогти. Насправді ви все-таки маєте задати це питання і відповісти на нього самостійно (тепер, коли ви це зрозуміли), щоб воно було корисним майбутнім шукачам. Самовідповідь вважається прийнятною.
paxdiablo

6
Дуже хороше рішення, але вам потрібно укласти подвійні лапки, інакше це не працюватиме зі змінними, які мають пробіли у своїх значеннях, наприклад: якщо ні "x% str1: bcd =%" == "x% str1%" echo It містить bcd
Helge Klein

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

"FINDSTR: Аргумент відсутній після / C. Один - шаблон не знайдено"
Berit Larsen

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

Я не знаю, чи це найкращий спосіб.


Мені потрібно було рекурсивно знаходити та порівнювати назви файлів. Це єдине рішення, яке працювало і для мене! Супер зручно і дуже просто.
SirJames

24

Для сумісності та простоти використання часто краще використовувати FIND для цього.

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

Метод із 78 пунктами (я вважаю, що я мав на увазі допис paxdiablo) буде відповідати лише випадку Case Sensitively, тому ви повинні поставити окрему перевірку для кожного варіанту випадку на кожну можливу ітерацію, яку ви хочете відповідати.

(Який біль! Усього 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
Це насправді не варіант, тому що вам все одно потрібно виділити символи для порівняння "ЯКЩО". ЯКЩО не відповідатимуть умовам "Лайк", оскільки ОП та конкретні рішення, на які я відповів, шукають.,
Бен Персонік

Привіт Бен, не звертайтеся до інших відповідей за кількістю балів, які вони мають. Це, ймовірно, зміниться. Будь ласка, оновіть свою відповідь, посилаючись на іншу відповідь, на ім'я автора цієї відповіді або на коротку фразу, що описує техніку, що використовується у цій відповіді.
телефонінг

Привіт Телефон Tagger, це було б корисним коментарем три роки тому, коли я писав оригінальний пост, проте, як ви згадуєте, значення балів змінилися. Я вже не пам’ятаю, про яку посаду я мав на увазі, і сьогодні я б не посилався на них за значеннями балів. Все одно, дякую.
Ben Personick

Я озирнувся і, вважаю, мав на увазі 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's разом, щоб додатково кваліфікувати заяву за допомогою pipe. EG для управління сервісом (SC.exe)

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

Цей оцінює вихід запиту SC для служб оновлення Windows, який виходить як багаторядковий текст, знаходить рядок, що містить "стан", а потім виявляє, чи є слово "працює" на цьому рядку, і встановлює рівень помилок відповідно.


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

2
+1 належить, навіть якщо @Leptonator правильний із перевернутою логікою. Це просте і просте у використанні рішення.
Laryx Decidua

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

У питанні, яке ви посилаєте за допомогою SET, вирішується конкретна та унікальна потреба, тому там важливо згадати "SET". Однак, здається, це нічого не додає до поточної дискусії, оскільки метод передачі команди до команди FIND та тестування результату вже передбачений
Бен


0

Рішення, які шукають файл у підрядку, також можуть шукати рядок , наприклад. findабо findstr.
У вашому випадку найпростішим рішенням буде введення рядка в команду, а не подання імені файлу, наприклад.

Рядок з великим регістром:
echo "abcdefg" | find "bcd"

Ігнорувати випадок рядка:
echo "abcdefg" | find /I "bcd"

Якщо не знайдено відповідності, ви отримаєте порожню лінію відповіді на CMD і% ERRORLEVEL% встановлено на 1

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.