คำตอบที่เลือกใช้งานได้ แต่อาจต้องปรับปรุงบางอย่าง
- ตัวเลือกควรเริ่มต้นเป็นค่าเริ่มต้น
- จะเป็นการดีที่จะรักษา% 0 ไว้เช่นเดียวกับ args% 1 และ% 2 ที่ต้องการ
- มันกลายเป็นความเจ็บปวดที่ต้องมีบล็อก IF สำหรับทุกตัวเลือกโดยเฉพาะอย่างยิ่งเมื่อจำนวนตัวเลือกเพิ่มขึ้น
- จะเป็นการดีที่จะมีวิธีที่ง่ายและรัดกุมในการกำหนดตัวเลือกและค่าเริ่มต้นทั้งหมดได้อย่างรวดเร็วในที่เดียว
- จะเป็นการดีที่จะสนับสนุนอ็อพชันแบบสแตนด์อะโลนที่ทำหน้าที่เป็นแฟล็ก (ไม่มีค่าตามหลังอ็อพชัน)
- เราไม่รู้ว่าอาร์กิวเมนต์อยู่ในเครื่องหมายคำพูดหรือไม่ เราไม่ทราบว่ามีการส่งผ่านค่า arg โดยใช้อักขระที่ใช้ Escape หรือไม่ ดีกว่าที่จะเข้าถึงอาร์กิวเมนต์โดยใช้% ~ 1 และใส่การกำหนดไว้ในเครื่องหมายคำพูด จากนั้นแบตช์สามารถพึ่งพาการไม่มีเครื่องหมายคำพูดที่ปิดอยู่ แต่โดยทั่วไปแล้วอักขระพิเศษจะยังคงปลอดภัยโดยไม่ต้องหลบหนี (นี่ไม่ใช่การพิสูจน์สัญลักษณ์แสดงหัวข้อย่อย แต่จัดการกับสถานการณ์ส่วนใหญ่)
โซลูชันของฉันอาศัยการสร้างตัวแปร OPTIONS ที่กำหนดตัวเลือกทั้งหมดและค่าเริ่มต้น OPTIONS ยังใช้เพื่อทดสอบว่าตัวเลือกที่ให้มานั้นถูกต้องหรือไม่ โค้ดจำนวนมหาศาลจะถูกบันทึกโดยการจัดเก็บค่าตัวเลือกในตัวแปรที่ชื่อเดียวกับตัวเลือก จำนวนรหัสเป็นค่าคงที่โดยไม่คำนึงถึงจำนวนตัวเลือกที่กำหนด เฉพาะคำจำกัดความของ OPTIONS เท่านั้นที่ต้องเปลี่ยนแปลง
แก้ไข - นอกจากนี้โค้ด: loop จะต้องเปลี่ยนหากจำนวนอาร์กิวเมนต์ตำแหน่งบังคับเปลี่ยนไป ตัวอย่างเช่นบ่อยครั้งที่อาร์กิวเมนต์ทั้งหมดถูกตั้งชื่อซึ่งในกรณีนี้คุณต้องการแยกวิเคราะห์อาร์กิวเมนต์ที่เริ่มต้นที่ตำแหน่ง 1 แทนที่จะเป็น 3 ดังนั้นภายใน: ลูปทั้ง 3 จะกลายเป็น 1 และ 4 กลายเป็น 2
@echo off
setlocal enableDelayedExpansion
:: Define the option names along with default values, using a <space>
:: delimiter between options. I'm using some generic option names, but
:: normally each option would have a meaningful name.
::
:: Each option has the format -name:[default]
::
:: The option names are NOT case sensitive.
::
:: Options that have a default value expect the subsequent command line
:: argument to contain the value. If the option is not provided then the
:: option is set to the default. If the default contains spaces, contains
:: special characters, or starts with a colon, then it should be enclosed
:: within double quotes. The default can be undefined by specifying the
:: default as empty quotes "".
:: NOTE - defaults cannot contain * or ? with this solution.
::
:: Options that are specified without any default value are simply flags
:: that are either defined or undefined. All flags start out undefined by
:: default and become defined if the option is supplied.
::
:: The order of the definitions is not important.
::
set "options=-username:/ -option2:"" -option3:"three word default" -flag1: -flag2:"
:: Set the default option values
for %%O in (%options%) do for /f "tokens=1,* delims=:" %%A in ("%%O") do set "%%A=%%~B"
:loop
:: Validate and store the options, one at a time, using a loop.
:: Options start at arg 3 in this example. Each SHIFT is done starting at
:: the first option so required args are preserved.
::
if not "%~3"=="" (
set "test=!options:*%~3:=! "
if "!test!"=="!options! " (
rem No substitution was made so this is an invalid option.
rem Error handling goes here.
rem I will simply echo an error message.
echo Error: Invalid option %~3
) else if "!test:~0,1!"==" " (
rem Set the flag option using the option name.
rem The value doesn't matter, it just needs to be defined.
set "%~3=1"
) else (
rem Set the option value using the option as the name.
rem and the next arg as the value
set "%~3=%~4"
shift /3
)
shift /3
goto :loop
)
:: Now all supplied options are stored in variables whose names are the
:: option names. Missing options have the default value, or are undefined if
:: there is no default.
:: The required args are still available in %1 and %2 (and %0 is also preserved)
:: For this example I will simply echo all the option values,
:: assuming any variable starting with - is an option.
::
set -
:: To get the value of a single parameter, just remember to include the `-`
echo The value of -username is: !-username!
ไม่มีรหัสมากนัก โค้ดด้านบนส่วนใหญ่เป็นความคิดเห็น นี่คือรหัสเดียวกันโดยไม่มีความคิดเห็น
@echo off
setlocal enableDelayedExpansion
set "options=-username:/ -option2:"" -option3:"three word default" -flag1: -flag2:"
for %%O in (%options%) do for /f "tokens=1,* delims=:" %%A in ("%%O") do set "%%A=%%~B"
:loop
if not "%~3"=="" (
set "test=!options:*%~3:=! "
if "!test!"=="!options! " (
echo Error: Invalid option %~3
) else if "!test:~0,1!"==" " (
set "%~3=1"
) else (
set "%~3=%~4"
shift /3
)
shift /3
goto :loop
)
set -
:: To get the value of a single parameter, just remember to include the `-`
echo The value of -username is: !-username!
โซลูชันนี้มีอาร์กิวเมนต์สไตล์ Unix ภายในชุด Windows นี่ไม่ใช่บรรทัดฐานสำหรับ Windows โดยปกติแล้วแบตช์จะมีตัวเลือกนำหน้าอาร์กิวเมนต์ที่ต้องการและตัวเลือกจะ/
ขึ้นต้นด้วย
เทคนิคที่ใช้ในโซลูชันนี้สามารถปรับให้เข้ากับตัวเลือกรูปแบบ Windows ได้อย่างง่ายดาย
- ลูปการแยกวิเคราะห์มักจะมองหาตัวเลือกที่
%1
และจะดำเนินต่อไปจนกว่า arg 1 จะไม่ขึ้นต้นด้วย/
- ทราบว่าได้รับมอบหมายตลาดหลักทรัพย์จะต้อง
/
ถูกปิดล้อมอยู่ภายในคำพูดถ้ามีชื่อขึ้นต้นด้วย
SET /VAR=VALUE
ล้มเหลวในการ
SET "/VAR=VALUE"
ทำงาน ฉันกำลังทำสิ่งนี้ในการแก้ปัญหาของฉันอยู่แล้ว
- มาตรฐานติ๊ดสไตล์ของ Windows
/
เป็นไปได้ของมูลค่าการโต้เถียงครั้งแรกที่เริ่มต้นด้วย ข้อ จำกัด นี้สามารถกำจัดได้โดยใช้//
อ็อพชันที่กำหนดโดยนัยซึ่งทำหน้าที่เป็นสัญญาณเพื่อออกจากลูปการแยกวิเคราะห์อ็อพชัน ไม่มีอะไรจะถูกเก็บไว้สำหรับ//
"ตัวเลือก"
อัปเดต 2015-12-28:รองรับ!
ในค่าตัวเลือก
ในโค้ดด้านบนอาร์กิวเมนต์แต่ละรายการจะถูกขยายในขณะที่เปิดใช้งานส่วนขยายที่ล่าช้าซึ่งหมายความว่า!
มีแนวโน้มที่จะถูกปล้นหรืออื่น ๆ เช่น!var!
ขยาย นอกจาก^
นี้ยังสามารถถอดออกได้หาก!
มีอยู่ การแก้ไขเล็กน้อยต่อไปนี้ของโค้ดที่ไม่ได้แสดงความคิดเห็นจะลบข้อ จำกัด ดังกล่าวออก!
และ^
จะคงไว้ในค่าตัวเลือก
@echo off
setlocal enableDelayedExpansion
set "options=-username:/ -option2:"" -option3:"three word default" -flag1: -flag2:"
for %%O in (%options%) do for /f "tokens=1,* delims=:" %%A in ("%%O") do set "%%A=%%~B"
:loop
if not "%~3"=="" (
set "test=!options:*%~3:=! "
if "!test!"=="!options! " (
echo Error: Invalid option %~3
) else if "!test:~0,1!"==" " (
set "%~3=1"
) else (
setlocal disableDelayedExpansion
set "val=%~4"
call :escapeVal
setlocal enableDelayedExpansion
for /f delims^=^ eol^= %%A in ("!val!") do endlocal&endlocal&set "%~3=%%A" !
shift /3
)
shift /3
goto :loop
)
goto :endArgs
:escapeVal
set "val=%val:^=^^%"
set "val=%val:!=^!%"
exit /b
:endArgs
set -
:: To get the value of a single parameter, just remember to include the `-`
echo The value of -username is: !-username!