ไฟล์ Batch: ค้นหาว่าสตริงย่อยอยู่ในสตริงหรือไม่ (ไม่ใช่ในไฟล์)


208

abcdefgในแฟ้มชุดที่ฉันมีสตริง ฉันต้องการตรวจสอบว่าbcdอยู่ในสตริงหรือไม่

น่าเสียดายที่ดูเหมือนว่าโซลูชันทั้งหมดที่ฉันค้นหาค้นหาไฟล์สำหรับสตริงย่อยไม่ใช่สตริงสำหรับสตริงย่อย

มีวิธีแก้ปัญหาง่าย ๆ สำหรับเรื่องนี้หรือไม่?


5
BTW ก็มักจะอย่างใดอย่างหนึ่ง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 เนื่องจากนั่นไม่ใช่ข้อกำหนดของคำถามนี้คุณอาจจะต้องถามคำถามอื่นบางทีอาจจะเป็นการอ้างอิงกลับไปที่ลิงก์นี้ ไม่มีปัญหาการขาดแคลนคนเต็มใจที่จะช่วยเหลือ ในความเป็นจริงคุณยังคง shoud ถามคำถามนั้นและตอบด้วยตัวคุณเอง (ตอนนี้คุณคิดออกแล้ว) เพื่อที่จะเป็นประโยชน์สำหรับผู้ค้นหาในอนาคต การตอบรับด้วยตนเองถือว่ายอมรับได้
paxdiablo

6
วิธีแก้ปัญหาที่ดีมาก แต่คุณต้องใส่เครื่องหมายคำพูดคู่หรือไม่สามารถใช้กับตัวแปรที่มีช่องว่างในค่าตัวอย่างเช่นถ้าไม่ใช่ "x% str1: bcd =%" == "x% str1%" echo ประกอบด้วย bcd
Helge Klein

4
"'= str1 ไม่คาดคิดในเวลานี้"
Berit Larsen

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: อาร์กิวเมนต์หายไปหลังจาก / มีหนึ่งแบบ - ไม่พบรูปแบบ"
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.

สำหรับปัญหาเรื่องความอ่อนไหวของ case คุณสามารถใช้setlocal EnableExtensionsแล้วIF /Iทำการเปรียบเทียบ case insensitive
cychoi

1
นั่นไม่ใช่ตัวเลือกจริง ๆ เพราะคุณยังต้องแยกอักขระสำหรับการเปรียบเทียบ "IF" หากจะไม่ตรงกันในข้อกำหนด "ถูกใจ" เนื่องจาก OP และโซลูชันเฉพาะที่ฉันตอบว่ากำลังมองหา,
Ben Personick

สวัสดีเบ็นโปรดอย่าอ้างอิงคำตอบอื่น ๆ ตามจำนวนคะแนนที่มี มีแนวโน้มที่จะเปลี่ยนแปลง โปรดอัปเดตคำตอบของคุณโดยอ้างถึงคำตอบอื่น ๆ โดยใช้ชื่อผู้แต่งของคำตอบนั้นหรือวลีสั้น ๆ ที่อธิบายถึงเทคนิคที่ใช้ในคำตอบนั้น
phonetagger

สวัสดี Phone Tagger นั่นจะเป็นความคิดเห็นที่มีประโยชน์เมื่อสามปีที่แล้วเมื่อฉันเขียนโพสต์ต้นฉบับอย่างไรก็ตามเมื่อคุณพูดถึงค่าคะแนนที่มีการเปลี่ยนแปลงทั้งหมด ฉันจำไม่ได้ว่าโพสต์ใดที่ฉันอ้างถึงและฉันจะไม่อ้างอิงพวกเขาด้วยค่าคะแนนในวันนี้ ขอบคุณอยู่ดี
Ben Personick

ฉันมองไปรอบ ๆ และฉันเชื่อว่าฉันหมายถึง paxdiablo ดังนั้นฉันจึงแก้ไขข้อความเพื่อแสดงให้เห็นว่า
Ben Personick

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 ซึ่งออกมาเป็นข้อความหลายบรรทัดค้นหาบรรทัดที่มี "สถานะ" จากนั้นค้นหาว่าคำว่า "ทำงาน" เกิดขึ้นบนบรรทัดนั้นและตั้งข้อผิดพลาดตามระดับ


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" อย่างไรก็ตามดูเหมือนว่าจะไม่เพิ่มสิ่งใด ๆ ลงในการสนทนาปัจจุบันเนื่องจากวิธีการ
Ben Personick


0

โซลูชันที่ค้นหาไฟล์สำหรับสตริงย่อยสามารถค้นหาสตริงได้เช่น หรือfind ในกรณีของคุณทางออกที่ง่ายfindstr
คือการไพพ์สตริงลงในคำสั่งแทนที่จะใส่ชื่อไฟล์เช่น

สตริงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่:
echo "abcdefg" | find "bcd"

ละเว้นกรณีของสตริง:
echo "abcdefg" | find /I "bcd"

หากไม่พบข้อมูลที่ตรงกันคุณจะได้รับการตอบกลับของบรรทัดว่างในชุด CMD และ% ERRORLEVEL% เป็น 1

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.