Plik wsadowy: Sprawdź, czy podciąg jest w ciągu (nie w pliku)

208

W pliku wsadowym mam ciąg abcdefg. Chcę sprawdzić, czy bcdjest w ciągu.

Niestety wydaje się, że wszystkie rozwiązania, które znajduję, szukają w pliku podłańcucha, a nie ciągu podciągu.

Czy istnieje na to łatwe rozwiązanie?

Ben
źródło
5
BTW, to zazwyczaj albo Windowsi cmd albo to ms-dos. MS-DOS nie jest częścią systemu Windows przez długi czas.
paxdiablo,

Odpowiedzi:

288

Tak, możesz użyć podstawień i sprawdzić oryginalny ciąg:

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

%str1:bcd=%Nieco zastąpi bcdw str1pustym ciągiem, co różni się od oryginału.

Jeśli oryginał nie zawierał bcdłańcucha, zmodyfikowana wersja będzie identyczna.

Testowanie przy użyciu następującego skryptu pokaże go w akcji:

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

I wyniki różnych przebiegów:

c:\testarea> testprog hello

c:\testarea> testprog abcdef
It contains bcd

c:\testarea> testprog bcd
It contains bcd

Kilka uwag:

  • ifStwierdzenie jest mięso z tego rozwiązania, wszystko inne jest wsparcie rzeczy.
  • xPrzed dwóch stronach równości jest zapewnienie, że ciąg bcddziała w porządku. Chroni również przed niektórymi „niewłaściwymi” postaciami początkowymi.
paxdiablo
źródło
7
Jeśli szukasz sposobu na zamianę łańcucha w pętli FOR: stackoverflow.com/a/6310580/623622
Czarek Tomczak
60
To świetnie, ale starałem się, aby to zadziałało, gdy wartość wyszukiwania nie była stała (jak bcd), ale była zmienną. Po długim czasie w końcu to rozgryzłem. Przy założeniu, że searchVal został zadeklarowany: „x! Str1:% searchVal% =!” == „x% str1%”
Gary Brunton
7
@Gary, ponieważ nie był to jeden z wymagań tego pytania, prawdopodobnie powinieneś był zadać inne pytanie, być może odsyłając do tego jako odniesienie. Nie brakuje osób chętnych do pomocy. W rzeczywistości nadal powinieneś zadawać to pytanie i sam na nie odpowiadać (teraz, gdy już to rozgryzłeś), aby było przydatne dla przyszłych poszukiwaczy. Odpowiedź na pytanie jest uważana za dopuszczalną.
paxdiablo
6
Bardzo dobre rozwiązanie, ale musisz ująć w podwójne cudzysłowy, inaczej nie będzie działać ze zmiennymi, które mają spacje w swoich wartościach, np .: jeśli nie "x% str1: bcd =%" == "x% str1%" echo It zawiera bcd
Helge Klein
4
„” = str1 było w tej chwili nieoczekiwane ”
Berit Larsen
104

Możesz potokować łańcuch źródłowy findstri sprawdzić wartość, ERRORLEVELaby zobaczyć, czy łańcuch wzorca został znaleziony. Wartość zero oznacza sukces i wzorzec został znaleziony. Oto przykład:

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

Po uruchomieniu w CMD.EXE otrzymujemy:

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
źródło
„FINDSTR: Brak argumentu po / C. dostał jeden - nie znaleziono wzoru”
Berit Larsen
47

Zwykle robię coś takiego:

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

Przykład:

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

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

Wynik:

TRUE
FALSE

Nie wiem, czy to najlepszy sposób.

użytkownik839791
źródło
Musiałem rekurencyjnie znajdować i porównywać nazwy plików. To było jedyne rozwiązanie, które również działało dla mnie! Super poręczny i bardzo prosty.
SirJames,
24

Dla kompatybilności i łatwości użytkowania często lepiej jest użyć ZNAJDŹ, aby to zrobić.

Musisz także rozważyć, czy chcesz dopasować wielkość liter z rozróżnieniem wielkości liter.

Metoda z 78 punktami (wydaje mi się, że odnosiłem się do postu paxdiablo) będzie pasować tylko do Case Sensitively, więc musisz sprawdzić osobno dla każdej odmiany przypadku dla każdej możliwej iteracji, którą chcesz dopasować.

(Co za ból! Przy zaledwie 3 literach oznacza to 9 różnych testów w celu przeprowadzenia kontroli!)

Ponadto wiele razy lepiej jest dopasować wyjście polecenia, zmienną w pętli lub wartość zmiennej wskaźnikowej w partii / CMD, która nie jest tak prosta.

Z tych powodów jest to preferowana alternatywna metodologia:

Użyj: Znajdź [/ I] [/ V] „Znaki do dopasowania”

[/ I] (wielkość liter niewrażliwa) [/ V] (NIE może zawierać znaków)

Jako pojedyncza linia:

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

Wieloliniowy:

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

Jak wspomniano, jest to świetne dla rzeczy, których nie ma w zmiennych, które również pozwalają na podstawienie łańcucha:

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
źródło
w przypadku problemu z rozróżnianiem wielkości liter można setlocal EnableExtensionsnastępnie użyć IF /Iporównania bez rozróżniania wielkości liter.
znaczącooi
1
To nie jest tak naprawdę opcja, ponieważ nadal będziesz musiał izolować znaki dla porównania „JEŻELI”. JEŻELI nie pasują do warunków „Lubię to”, ponieważ szukają OP i konkretnych rozwiązań, na które odpowiedziałem.
Ben Personick
Cześć Ben, Proszę nie odnosić się do innych odpowiedzi przez liczbę punktów, które mają. To prawdopodobnie się zmieni. Zaktualizuj swoją odpowiedź, odwołując się do drugiej odpowiedzi, według nazwiska autora lub krótkiej frazy opisującej technikę zastosowaną w tej odpowiedzi.
fonetagger
Cześć, Tagger, to byłby pomocny komentarz trzy lata temu, kiedy napisałem oryginalny post, jednak jak wspominasz, wartości punktów się zmieniły. Nie pamiętam już, do którego wpisu się odnosiłam, i nie odniosłbym się do nich dzisiaj według wartości punktowych. W każdym razie dzięki.
Ben Personick
Rozejrzałem się i wydaje mi się, że miałem na myśli paxdiablo, więc poprawiłem tekst, aby to pokazać.
Ben Personick
10

Jeśli wykrywasz obecność, oto najprostsze rozwiązanie:

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

Działa to doskonale w przypadku upuszczania danych wyjściowych poleceń systemu Windows do zmiennej boolean. Po prostu zastąp echo poleceniem, które chcesz uruchomić. Możesz także połączyć łańcuch Findstr, aby dodatkowo zakwalifikować instrukcję za pomocą potoków. EG do kontroli usług (SC.exe)

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

Ten ocenia wynik zapytania SC Query dla usług aktualizacji systemu Windows, który pojawia się jako tekst wielowierszowy, znajduje wiersz zawierający „stan”, a następnie sprawdza, czy słowo „uruchomione” występuje w tym wierszu, i odpowiednio ustawia poziom błędu.

praca
źródło
6
Wyciągnąłeś swoje IF Instrukcja wstecz. Patrząc na oryginał z abcdefg i przerzucasz logikę. To działa. Sposób, w jaki go masz, tak nie jest. 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 jest należne, mimo że @Leptonator jest poprawny z logiką odwróconą. To proste i łatwe w użyciu rozwiązanie.
Laryx Decidua
2

Prawdopodobnie przychodzę trochę za późno z tą odpowiedzią, ale zaakceptowana odpowiedź działa tylko w celu sprawdzenia, czy „ciąg zakodowany na stałe” jest częścią ciągu wyszukiwania.

W przypadku wyszukiwania dynamicznego musisz to zrobić:

SET searchString=abcd1234
SET key=cd123

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

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

Uwaga: Możesz wziąć dwie zmienne jako argumenty.

Andy Sug
źródło
1

Lepsza odpowiedź była tutaj :

set "i=hello " world"
set i|find """" >nul && echo contains || echo not_contains
T.Todua
źródło
W pytaniu, które łączysz za pomocą SET, jest zaspokojenie konkretnej i unikalnej potrzeby, dlatego należy wspomnieć o „SET”. Jednak wydaje się, że nic nie dodaje do bieżącej dyskusji, ponieważ metoda
potokowania
1
ECHO %String%| FINDSTR /C:"%Substring%" && (Instructions)
Riccardo La Marca
źródło
0

Rozwiązania, które wyszukują w pliku podciąg, mogą również wyszukiwać ciąg , np. findlub findstr.
W twoim przypadku łatwym rozwiązaniem byłoby wstawienie ciągu znaków do polecenia zamiast podania nazwy pliku, np.

rozróżniana jest wielkość liter:
echo "abcdefg" | find "bcd"

zignoruj ​​wielkość liter ciągu:
echo "abcdefg" | find /I "bcd"

JEŻELI nie znaleziono dopasowania, otrzymasz odpowiedź na pustym wierszu na CMD i% ERRORLEVEL% ustawiony na 1

Zimba
źródło