ยัติภังค์หมายถึงอะไรในไฟล์แบตช์ของ Windows


1

โดยเฉพาะฉันมีปัญหาในการเข้าใจเครื่องหมายขีดคั่นในบรรทัดต่อไปนี้ซึ่งมาจาก วิกิพีเดีย

if not -%1-==-- echo Argument one provided
if -%1-==-- echo Argument one not provided & exit /b

เพื่อทดสอบว่าตัวแปรนั้นมีอยู่จริงหรือถูกนิยามมีสองวิธีที่ฉันเรียนรู้จาก ที่นี่ :

IF DEFINED MyVar (ECHO MyVar IS defined) ELSE (ECHO MyVar is NOT defined)

IF "%MyVar%"=="" (ECHO MyVar is NOT defined) ELSE (ECHO MyVar IS defined)

ดังนั้นเครื่องหมายยัติภังค์ (1) รอบ ๆ อาร์กิวเมนต์% 1 และ (2) เครื่องหมายยัติภังค์หลังเครื่องหมาย == หมายถึงอะไร


1
ความคิดเห็นหนึ่งรายการของคุณที่กล่าวถึง %% นั้นใช้สำหรับการวนซ้ำในไฟล์แบตช์เช่น %% f ไม่ใช่สำหรับพารามิเตอร์บรรทัดคำสั่งแบตช์% 1% 2% 3 จากบรรทัดคำสั่งคุณสามารถทำได้ for %1 in (*.*) do @echo %1 และมันจะคลุมเครือที่จะทำเช่นนั้นในไฟล์แบตช์ดังนั้นสำหรับคำสั่งเมื่อภายในไฟล์แบตช์ใช้ %% แต่พารามิเตอร์แบทช์ (ซึ่ง btw ซึ่งเคยเป็นไฟล์แบตช์เท่านั้น) จะเป็น% 1,% 2 ฯลฯ
barlop

เรียน midnite: นี่เป็นปี 2015 ทำไมคุณยังคงใช้ภาษาการเขียนโปรแกรมที่แย่ในการเขียนสคริปต์เป็นชุด คุณสามารถเปลี่ยนเป็น VBScript, JScript, PowerShell หรืออย่างใดอย่างหนึ่ง ตัวเลือกอื่น ๆ อีกมากมาย .
unforgettableid

"อย่างไรก็ตามสิ่งเหล่านี้จำเป็นต้องมีการติดตั้งล่ามภาษาสคริปต์ก่อนจึงจะสามารถใช้งานได้" - ไม่เป็นอันตรายต่อการเรียนรู้เพิ่มเติมโดยที่มันจะทำงานบนพีซีส่วนใหญ่ ;-)
midnite

1
@ midnite ฉันเดาด้วยแบทช์มันมีข้อ จำกัด เกี่ยวกับจำนวนของปัญหาที่คุณสามารถพบได้ดังนั้นฉันเรียนรู้ตลอดหลายปีที่ผ่านมาโดยการตั้งคำถามและเล่นซอและดูเหมือนว่าจะมีอัจฉริยะที่คิดสิ่งที่ไม่ได้เขียนไว้ในเอกสารอ้างอิงใด ๆ เมื่อมันยากมาก ตัวอย่างเช่น .. เดฟเบ็นแฮมและเจบ .. ฉันคิดว่าโพสต์ทั้งที่นี่และในฟอรั่ม dostips .. และสำหรับการอ้างอิงมีต้นฉบับ vfrazee.com/ms-dos/6.22/help ที่ปรากฏใน DOS เมื่อคุณเรียกใช้ HELP.COM (คุณสามารถคลิกเช่นถ้าเป็นตัวอย่าง) และมี ss64.com/nt
barlop

1
โปรแกรม C เล็ก ๆ เหล่านี้สามารถช่วยแสดงให้เห็นว่าโปรแกรมแบ่งสิ่งต่าง ๆ เป็นพารามิเตอร์อย่างไรเพื่อช่วยแก้ไขปัญหาราคาคำพูด superuser.com/questions/944745/sed-command-with-apostrophe/... และถ้าคุณเคยลองลึก ๆ แล้ว jeb และ dbenham ได้เขียนบทความเกี่ยวกับการทำงานของล่ามแบบแบตช์ .. พบได้จากการทดสอบมากกว่าการอ้างอิงใด ๆ stackoverflow.com/questions/4094699/...
barlop

คำตอบ:


6

พิจารณาสิ่งนี้

C:\>if not -%1-==-- echo Argument one provided
Argument one provided

C:\>if not P%1P==PP echo Argument one provided
Argument one provided

มันควรจะเห็นได้ชัดว่ามีการใช้อักขระลบ / ยัติภังค์เพื่ออำนวยความสะดวกในการกำหนดค่าที่ว่างเปล่า สัญลักษณ์เฉพาะนั้นไม่มีความหมายพิเศษในนิพจน์นั้น - มันจะถือว่าเหมือนกับอักขระที่ไม่ใช่พิเศษอื่น ๆ

เราสามารถเพิ่มช่องว่างเพื่อให้ชัดเจนว่า == ผู้ประกอบการคือ ไม่ ถูกแก้ไขโดยตัวละครโดยรอบ

C:\>if not P%1P == PP echo Argument one provided
Argument one provided

โดยทั่วไปจะเป็นการดีกว่าหากใช้วิธีการทั่วไปที่ผู้คนจำนวนมากจะเข้าใจได้ในทันที (เช่นการใช้เครื่องหมายคำพูด)

C:\>if not "%1"=="" echo Argument one provided
Argument one provided

ด้วย DOS และ Windows รุ่นแรก ๆ ฉันเชื่อว่ามีปัญหาบางอย่าง (ซึ่งฉันจำไม่ได้) ด้วยการใช้เครื่องหมายคำพูดที่ทำให้ผู้คนที่ใช้ตัวอักษรที่พิมพ์ได้ด้วยวิธีนี้ ฉันไม่ได้ลองกรณีที่% 1 มีเครื่องหมายคำพูดยกตัวอย่างเช่น


ฉันเห็น. ขอบคุณมาก ๆ. ดังนั้นโดยพื้นฐานแล้วมันหมายถึงการต่ออักขระสองตัวเข้าด้วยกันก่อนและหลังตัวแปรใช่ไหม? OTOH ฉันพยายามใช้ defined คำหลักเพื่อตรวจสอบว่าพารามิเตอร์ที่มีอยู่ ทั้งสอง IF DEFINED %1 และ IF DEFINED %%1 ดูเหมือนจะไม่ทำงาน คุณจะให้คำแนะนำบางอย่างกับฉันได้ไหม
midnite

คุณเขียน "อักขระลบ / ยัติภังค์ถูกใช้เพื่อทำให้การกำหนดค่าว่างง่าย" & lt; --- คำว่า "ลดความซับซ้อน" น่าจะไม่ใช่คำเดียวที่ดีในการใช้ 'เพราะมันไม่ได้ลดความซับซ้อน (สิ่งที่ทำให้เรียบง่ายจะหมายถึง) แต่อย่างที่คุณทราบมันป้องกันข้อผิดพลาดเมื่อไม่มีข้อโต้แย้ง
barlop

@barlop: ขอบคุณสำหรับความคิดเห็น แก้ไขคำตอบแล้ว
RedGrittyBrick

การแก้ไขที่ดี แต่ท้ายที่สุดคุณเขียนว่า "ด้วย DOS และอาจเป็นรุ่นแรก ๆ ของ Windows ฉันเชื่อว่ามีปัญหาบางอย่าง (ซึ่งฉันจำไม่ได้) ด้วยการใช้เครื่องหมายคำพูด" & lt; - ยังเป็น กำลังใช้ "% 1" ดูคำตอบของฉัน .. ตอนแรกฉันพูดว่าเครื่องหมายคำพูดนั้นยอดเยี่ยมประมาณ% 1 จากนั้น supercat แสดงความคิดเห็นและฉันแก้ไขมัน
barlop

คุณเขียน "ยังไม่ได้ลองกรณีที่% 1 มีเครื่องหมายคำพูดเช่น" & lt; - หากผู้ใช้ให้และคุณไม่ทำ "% 1" ก็โอเค หากผู้ใช้ให้พวกเขาและคุณเพิ่มด้วย "% 1" ก็ไม่เป็นไร
barlop

4

สิ่งสำคัญคือเมื่อใช้% 1 เพื่อวางบางสิ่งไว้รอบ ๆ เพื่อป้องกันไม่ให้แฟ้มชุดงานแตกเมื่อ% 1 ว่างเปล่าเนื่องจาก% 1 ไม่ใช่ตัวแปรจึงได้รับการแทนที่ด้วยค่าเช่นการฉีด SQL ตัวอย่างของการฉีดเป็นชุด และเมื่อไม่มีสิ่งใดมีค่าและ% 1 อยู่ใน IF คุณจะได้รับรหัสที่เสียหาย if %1=="" กลายเป็น if == "" และให้ข้อผิดพลาด

สำหรับสาเหตุถ้าการกำหนดไม่ทำงานบน% 1,% 1 เป็นค่าที่ไม่ใช่ตัวแปรดังนั้นการกำหนดจึงไม่ทำงานที่นั่น สำหรับรหัสที่ใช้งานได้กับ% 1 ว่างเปล่าคุณต้องใช้รหัสที่จะไม่แตกเมื่อ% 1 ถูกแทนที่ด้วยอะไร ลอง if "%1"=="" หรือลอง if [%1]==[]

การพูด -% 1 ดูสับสนเล็กน้อยมันไม่เหมือนกับการประชุมที่ดีสำหรับฉัน! ในทางเทคนิคคุณสามารถทำได้ if a%1==a%1 หรือ if %1a==%1a แต่การประชุมมีแนวโน้มที่จะเป็น []

คุณสามารถใช้เครื่องหมายคำพูดหรือ [] หรือตัวละครอะไรก็ได้ แต่เนื่องจาก supercat ได้ชี้ให้เห็นในความคิดเห็นราคาไม่ใช่ความคิดที่ดีเกี่ยวกับ% 1 (เพราะถ้า% 1 มีช่องว่างผู้ใช้จะใส่เครื่องหมายอัญประกาศในสิ่งที่ได้รับการส่งผ่านไปยัง% 1 และถ้ามีช่องว่างใน% 1 และในไฟล์แบตช์ที่คุณใส่เครื่องหมายคำพูดไว้รอบ ๆ % 1 เครื่องหมายคำพูดจะถูกยกเลิก และช่องว่างที่ไม่ได้ระบุไว้จะทำให้เกิดข้อผิดพลาด)

หากคุณทำ IF บนบรรทัดคำสั่งและไม่ทดสอบตัวแปรใด ๆ คุณจะไม่มี% 1 และคุณไม่จำเป็นต้องมี [] คุณจะพูดว่า IF "a b c"=="a b c" echo a หรือ IF a==b echo a หากในไฟล์แบตช์คุณมักจะมี% 1 และแทนที่จะใช้เครื่องหมายคำพูดรอบ ๆ % 1 ใช้เช่น หนึ่งหรือสองตัวอักษรรอบตัวเช่น [%1] และใช้เครื่องหมายคำพูดหากคุณต้องการรักษาช่องว่างและไม่ใช่% 1 เช่น เช่น. IF [%1]==[a] หรือ IF [%1]==["a b"] echo a อย่าทำ "%1" เนื่องจาก% 1 อาจมีเครื่องหมายคำพูดอยู่แล้วซึ่งเครื่องหมายคำพูดของคุณจะถูกยกเลิกและถ้า% 1 มีช่องว่างถ้า if คำสั่งแตก

หากคุณอยู่ในบรรทัดคำสั่งและกำลังทดสอบตัวแปรมันขึ้นอยู่กับว่าตัวแปรนั้นมีเครื่องหมายคำพูดหรือไม่ คุณสามารถดูเนื้อหา

เป็นไปได้ที่ตัวแปรจะมีช่องว่างและไม่มีเครื่องหมายคำพูด

ดังนั้นในกรณีบรรทัดคำสั่งนี้การใส่เครื่องหมายคำพูดรอบ ๆ % a% จะไม่เพิ่มเครื่องหมายคำพูดคู่และคุณต้องใส่เครื่องหมายคำพูดรอบ ๆ % a% ถ้าคุณต้องการทดสอบกับ "a b"

C:\>set a=a b

C:\>echo %a%
a b

C:\>IF %a%=="a b" echo sdf
b=="a b" was unexpected at this time.

C:\>IF "%a%"=="a b" echo sdf
sdf

So ^^^ we want "%a%"

ในกรณีที่% a% มีเครื่องหมายคำพูดมันจะเป็นกรณีอื่น

C:\>set a="a b"

C:\>echo %a%
"a b"

C:\>IF %a%=="a b" echo a
a

C:\>IF "%a%"=="a b" echo a
b""=="a b" was unexpected at this time.

C:\>

^^^^ So there we want %a% without quotes around it.

ดังนั้นทุกคำถามว่าตัวแปรหรือพารามิเตอร์มีเครื่องหมายคำพูดหรือไม่ หาก% 1 มีช่องว่างในนั้นจะมีเครื่องหมายคำพูด ดังนั้นเรารู้ว่าถ้าเราเปรียบเทียบ% 1 กับ "a b" ดังนั้น w จะไม่ทำ "% 1" และถ้า% 1 ไม่มีเครื่องหมายคำพูดมันจะไม่มีช่องว่างดังนั้นเราจะไม่ทำ "% 1" ดังนั้นฉันคิดว่าคุณไม่ต้องการทำ "% 1" ดังนั้นหาก% 1 มีช่องว่างจะมีเครื่องหมายคำพูดอยู่ภายใน% 1 และช่องว่างนั้นจะถูกเก็บไว้แล้ว

ฉันขีดด้านล่างตามความคิดเห็นของ supercat และฉันเพิ่มมากขึ้นในโพสต์ของฉันด้านบน

เครื่องหมายคำพูดนั้นดีที่สุดประมาณ% 1 แทนที่จะเป็น [] หรือตัวละครบางตัวเช่น A หรือ - เพราะตัวอย่างเช่นถ้าคุณใช้ [] มันจะไม่รักษาช่องว่าง

C: \ & gt; ถ้า [d a b] == [d a b] echo sdf

a ไม่คาดคิดในเวลานี้

พูด if "d a b" ที่จะทำงาน ดังนั้น if "%1" ดีกว่าตัวละครอื่น ๆ ที่ชอบ if [%1] หรือ a%1a หรือ -%1


2
ทางเดียวเท่านั้น %1 จะขยายเป็นบางสิ่งบางอย่างที่มีช่องว่างถ้าอาร์กิวเมนต์มีเครื่องหมายอัญประกาศ ในกรณีนั้นโดยรอบ %1 ด้วยเครื่องหมายอัญประกาศจะทำให้เกิดพฤติกรรมที่ไม่สมบูรณ์และการล้อมรอบด้วยสิ่งอื่นควรใช้งานได้
supercat

2
เกิดอะไรขึ้นถ้าอาร์กิวเมนต์ที่ยกมามีช่องว่าง?
supercat

1
@supercat อาฉันเห็นด่างดี if "" 2""==""2"" echo a ล้มเหลว และในกรณีที่ไม่มีใครรู้ .. "" จะมีผลในการเปิดและปิดข้อความ
barlop

1
@ mididite มันมีความคล้ายคลึงกับการต่อข้อมูลที่คุณเห็นในภาษาขั้นสูง แต่ฉันคิดว่าการทำงานไม่มาก 'cos กับ java ฯลฯ การต่อข้อมูลเป็นสองหน่วยงานแยกจากกัน ด้วย cmd "asdf""asdf" ไม่ได้เข้าร่วมสองวัตถุแยกกัน "แรกหมายถึงเปิดโหมดที่ช่องว่างและตัวละครอื่น ๆ จะถูกเก็บไว้ถัดไป" หมายถึงปิดโหมดนั้น ถัดไปเปิดใช้งาน ดังนั้นคุณสามารถพูดว่า "asdf asdf" หรือคุณสามารถพูดได้ asdf" "asdf ดังนั้น 2"" ไม่ควรดูยุ่งยากเกินไป (แต่บางครั้งการหาวิธีการทำงานของชุดคำสั่ง / ชุดเป็นเรื่องยุ่งยาก)
barlop

1
@ midid ฉันยังสงสัยว่าไฟล์แบทช์ (โดยทั่วไป) แยกสตริงและตัวเลขแม้ว่าคำสั่งหรือฟังก์ชั่นบางอย่างภายในคำสั่งทำ ไม่ว่าจะเป็น 2 หรือตัวเลขก็แปลว่า .. ถ้าคุณพูด echo 2 ไม่มีการแปลง 2 เป็นสตริง ฉันคิดว่าในทางเทคนิคกับคอมพิวเตอร์มันเข้ารหัสทั้งหมด (ฉันจะไม่พูดอักขระ) squiggles / glyphs บางคนอาจดูที่การนำเสนอถ้าคำพูดหรือไม่แล้วปฏิบัติตามนั้นเป็นตัวเลข (สำหรับการคำนวณ) หรือเป็นสตริง หรือเช่นเดียวกับร่ายมนตร์ที่เข้ารหัสพวกเขาไม่ว่าจะเป็นตัวเลขหรือสตริง
barlop

1

ไม่แน่ใจว่าคุณค่อนข้างจะได้รับดังนั้นให้ฉันดูว่าฉันสามารถทำให้มันง่ายขึ้น

สมมติว่าไฟล์แบทช์ของคุณได้รับค่า %1 บนบรรทัดคำสั่งและคุณต้องการดูว่าเป็น "cat" หรือ "dog" คุณสามารถทดสอบสิ่งต่อไปนี้:

if %1 == cat goto CAT
if %1 == dog goto DOG
REM Default: Complain about no dog or cat
goto OOPS
:CAT
echo I'm a cat!
REM Successful, so skip to end
goto END
:DOG
echo I'm a dog!
goto END
:OOPS
echo I didn't see a cat or dog!
REM This just falls through to the end
:END

%1 ถูกแทนที่ด้วยข้อความของแมวหรือสุนัข (สมมุติว่าสุนัข) ดังนั้นล่ามจะเห็นสิ่งนี้:

if dog == cat goto CAT
if dog == dog goto DOG

แต่ถ้าบุคคลที่เรียกใช้สคริปต์ไม่มีค่าในบรรทัดคำสั่งล่ามจะเห็นสิ่งนี้:

if  == cat goto CAT
if  == dog goto DOG

นั่นคือไวยากรณ์ที่ไม่ถูกต้องและจะสร้างข้อผิดพลาด ดังนั้นการประชุมคือการรวม 1 ตัวอักษรหรือมากกว่าและทดสอบเพื่อไม่ให้มีตัวแปรก่อนสิ่งนี้:

if %1* == * goto OOPS
REM If no value passed in, this is seen as  if * == *  which evaluates to true
if %1 == cat goto CAT
if %1 == dog goto DOG
goto END
:CAT
echo I'm a cat!
goto END
:DOG
echo I'm a dog!
goto END
:OOPS
echo You were supposed to include a type of pet!
:END

ถ้า %1 ประเมินว่าไม่มีสิ่งใดอักขระพิเศษยังคงอยู่ที่นั่นเพื่อให้ไวยากรณ์ถูกต้อง ฉันใช้ *แต่คำพูดหรือเครื่องหมายอัศเจรีย์ก็เหมือนกันเช่นกัน "%1" หรือ %1!เช่นเดียวกับยัติภังค์เช่น --%1 หรือ -%1-ฯลฯ

ผู้ชายฉันไม่อยากจะเชื่อเลยว่ายังจำได้ทั้งหมด :-) ฉันหวังว่านี่จะช่วยได้!


คุณเขียนว่า "แต่ถ้าคนที่เรียกใช้สคริปต์ไม่มีตัวแปร" & lt; - คุณอาจหมายถึง "ค่า" เพราะมันมีค่ามากกว่าตัวแปร มันกำลังส่งผ่านข้อมูลบางทีอาจบอกได้ว่ามีค่า และสำหรับวิธีการส่งผ่าน (ในการเขียนโปรแกรมภาษาขั้นสูงบางอย่างคุณสามารถมี 'pass by value' หรือ 'pass by reference' ฉันเดาว่าจะมีคนบอกว่าสิ่งนี้ผ่านการฉีด!
barlop

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