การแยกวิเคราะห์อาร์กิวเมนต์ที่เป็นทางเลือกของไฟล์ค้างคาวของ Windows


84

ฉันต้องการไฟล์ bat ของฉันเพื่อยอมรับอาร์กิวเมนต์ที่มีชื่อซึ่งเป็นทางเลือกหลายรายการ

mycmd.bat man1 man2 -username alice -otheroption

ตัวอย่างเช่นคำสั่งของฉันมีพารามิเตอร์บังคับ 2 พารามิเตอร์และพารามิเตอร์ทางเลือกสองตัว (- ชื่อผู้ใช้) ที่มีค่าอาร์กิวเมนต์เป็น alice และ -otheroption:

ฉันต้องการสามารถดึงค่าเหล่านี้เป็นตัวแปรได้

เพียงแค่โทรหาใครก็ได้ที่แก้ปัญหานี้แล้ว มนุษย์ไฟล์ค้างคาวเหล่านี้เป็นความเจ็บปวด


12
มีเหตุผลใดที่คุณต้องทำในไฟล์ BAT และไม่พูดใน VBScript? อาจมีวิธีทำในไฟล์ BAT แต่ยึดติดกับวิธีการไฟล์ BAT คุณ "กำลังเข้าสู่โลกแห่งความเจ็บปวดลูกชาย" :-)
Alek Davis

ที่ดีไปกว่านั้นคือการใช้ PowerShell มีการจัดการพารามิเตอร์ขั้นสูงและในตัว
Bill_Stewart

2
@AlekDavis คุณอาจจะพูดถูก แต่ฉัน VBScript-phobic สูงมาก ถ้าฉันเคยพบว่าตัวเองต้องใช้ VBScript ฉันคิดว่าฉันอยู่ในโลกแห่งความเจ็บปวดแล้ว ฉันจะเขียนไฟล์แบตช์ให้ตัวเองอย่างมีความสุขเพื่อทำให้บางสิ่งบางอย่างเป็นอัตโนมัติถ้าฉันต้องการทำให้เป็นประโยชน์มากขึ้นสำหรับผู้คนฉันจะเพิ่มข้อโต้แย้ง บ่อยครั้งบางส่วนเป็นทางเลือก ตั้งแต่ฉันออกจากโลกของการธนาคารฉันคิดไม่ถึงหรือมีคนแนะนำว่า "คุณจะต้องใช้ VBScript สำหรับสิ่งนั้น"
icc97

@chickeninabiscuit: ลิงก์ไม่ทำงานอีกต่อไป เวอร์ชันเครื่อง Wayback ทำ http://web.archive.org/web/20090403050231/http://www.pcguide.com/vb/showthread.php?t=52323ผมไม่ทราบว่าถ้าผมแก้ไขความคิดเห็นของคุณถ้ามันจะเปลี่ยนให้มีลักษณะเหมือนฉันไม่ทำงานหรือไม่ฉันแค่จะไปวางไว้ที่นี่แทน:
Brent Rittenhouse

คำตอบ:


113

แม้ว่าฉันมักจะเห็นด้วยกับความคิดเห็นของ @AlekDavisแต่ก็มีหลายวิธีในการทำเช่นนี้ใน NT shell

วิธีการที่ฉันจะใช้ประโยชน์จากคำสั่งSHIFTและIF ตามเงื่อนไขการแยกสาขาอะไรทำนองนี้ ...

@ECHO OFF

SET man1=%1
SET man2=%2
SHIFT & SHIFT

:loop
IF NOT "%1"=="" (
    IF "%1"=="-username" (
        SET user=%2
        SHIFT
    )
    IF "%1"=="-otheroption" (
        SET other=%2
        SHIFT
    )
    SHIFT
    GOTO :loop
)

ECHO Man1 = %man1%
ECHO Man2 = %man2%
ECHO Username = %user%
ECHO Other option = %other%

REM ...do stuff here...

:theend

1
SHIFT /2การเลื่อนเริ่มต้นที่ arg 2 ไม่เลื่อนสองครั้ง ไม่ควรแทนที่ด้วยSHIFT & SHIFT?
dbenham

2
ตกลง - ฉันเห็นว่าทำไมโค้ดถึงใช้งานได้ - ในที่สุด SHIFT ในลูปก็ย้ายตัวเลือกไปที่ arg 1 และไม่มีอันตรายใด ๆ เกิดขึ้น (โดยปกติ) แต่ SHIFT / 2 เริ่มต้นเป็นข้อบกพร่องที่จะทำให้ผลลัพธ์เสียหายหากค่า arg 1 เกิดขึ้นตรงกับชื่อตัวเลือกใดชื่อหนึ่ง mycmd.bat -username anyvalue -username myName -otheroption othervalueลองใช้ ผลลัพธ์ควรเป็น user = myName, other = othervalue; แต่รหัสให้ user = -username, other = othervalue ข้อบกพร่องได้รับการแก้ไขโดยแทนที่SHIFT /2ด้วยSHIFT & SHIFT.
dbenham

2
@Christian - ewall ไม่ถูกต้องเกี่ยวกับ;- ไม่สามารถใช้แทน&ได้
dbenham

1
นี่เป็นการเริ่มต้นที่ดี แต่ฉันเห็น 3 ปัญหา ขั้นแรก: a) หลังจากบรรทัดที่ 10 %1และ%2ถูก "ใช้" ข) เดียวSHIFTในสาย 11 การเคลื่อนไหวค่าของการ%2ลดลง 1 ตำแหน่งและเป็นแล้วใช้ได้ (อีกครั้ง) ในฐานะ%1และ "ไม่ได้ใช้" ค่าของสามารถใช้ได้เป็น%3 %2ค) IFในสาย 13 เห็นอย่างนี้แล้ว "มือสอง" ค่าจากที่ขณะนี้อยู่ใน%2 %1d) หาก "ชื่อผู้ใช้" จากบรรทัดที่ 10 ดูเหมือน"-otheroption"จะถูกใช้อีกครั้งและotherจะถูกตั้งเป็นค่าใหม่%2ซึ่งน่าจะเป็นชื่อของตัวเลือกถัดไป --->
Kevin Fegan

2
ปัญหาที่ 2: ในคำถาม OP -otheroptionไม่ได้ตามด้วยค่าดังนั้นจึงอาจหมายถึง-Flagตัวเลือกประเภทและไม่ควรใช้อาร์กิวเมนต์ที่ 2 3: หากอาร์กิวเมนต์%1ไม่ได้รับการจัดการโดยIFคำสั่งภายในอาร์กิวเมนต์จะถูกละเว้นโดยไม่โต้ตอบ รหัสน่าจะแสดงข้อความที่ระบุว่าไม่ใช่ตัวเลือกที่ถูกต้อง ซึ่งสามารถทำได้โดยการเพิ่มคำสั่งSHIFTและGOTO :loopคำสั่งที่จำเป็นลงในIFข้อความภายในหรือโดยการเพิ่มELSEคำสั่ง
Kevin Fegan

75

คำตอบที่เลือกใช้งานได้ แต่อาจต้องปรับปรุงบางอย่าง

  • ตัวเลือกควรเริ่มต้นเป็นค่าเริ่มต้น
  • จะเป็นการดีที่จะรักษา% 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!

ขอบคุณสำหรับวิธีแก้ปัญหาที่ยอดเยี่ยมฉันชอบสิ่งนี้มากกว่าที่ยอมรับว่าเป็นคำตอบ สิ่งเดียวที่คุณพลาดไปคือการบอกวิธีใช้พารามิเตอร์ที่มีชื่อในสคริปต์ชุดตัวอย่างเช่น echo% -username%
Roboblob

1
โซลูชันที่หรูหรามาก หากคุณพิจารณาใช้สิ่งนี้โปรดทราบว่าโค้ดที่ให้ไว้จะเริ่มแยกวิเคราะห์ที่อาร์กิวเมนต์ 3 นี่ไม่ใช่สิ่งที่คุณต้องการในกรณีทั่วไป แทนที่ "3" ด้วย "1" เพื่อแก้ไขปัญหานี้ @dbenham คงจะดีถ้าคุณสามารถทำให้สิ่งนี้ชัดเจนยิ่งขึ้นในโพสต์ต้นฉบับฉันอาจไม่ใช่คนเดียวที่สับสนในตอนแรก
ocroquette

@ocroquette - จุดดี ฉันไม่มีทางเลือกมากนักเนื่องจากต้องตอบคำถามที่เจาะจง แต่โค้ดจะต้องได้รับการแก้ไขเมื่อจำนวนอาร์กิวเมนต์ตำแหน่งบังคับเปลี่ยนไป ฉันจะพยายามแก้ไขคำตอบเพื่อให้ชัดเจน
dbenham

ฉันรักสิ่งนี้. ขอบคุณสำหรับวิธีแก้ปัญหามันยังคงใช้งานได้ในปี 2019 สำหรับการเขียนสคริปต์ IDE บางอย่าง!
Robert Smith

18

หากคุณต้องการใช้อาร์กิวเมนต์ที่เป็นทางเลือก แต่ไม่ได้ตั้งชื่ออาร์กิวเมนต์แสดงว่าวิธีนี้ใช้ได้กับฉัน ฉันคิดว่านี่เป็นรหัสที่ง่ายกว่ามากในการติดตาม

REM Get argument values.  If not specified, use default values.
IF "%1"=="" ( SET "DatabaseServer=localhost" ) ELSE ( SET "DatabaseServer=%1" )
IF "%2"=="" ( SET "DatabaseName=MyDatabase" ) ELSE ( SET "DatabaseName=%2" )

REM Do work
ECHO Database Server = %DatabaseServer%
ECHO Database Name   = %DatabaseName%

IF "%1"==""จะล้มเหลวหากอาร์กิวเมนต์มีเครื่องหมายคำพูดเอง เพียงใช้สัญลักษณ์อื่นที่ไม่ใช่สัญลักษณ์แทนเช่น. _ = [] # etc
Fr0sT

2
ฉันไม่คิดว่าจะได้ผลเว้นแต่ผู้ใช้จะรู้จักใช้ "" แทนอาร์กิวเมนต์ มิฉะนั้นฉันจะตั้งชื่อ DB แต่ปล่อยให้เซิร์ฟเวอร์ DB ว่างได้อย่างไร
Sean Long

คุณเห็นว่าคำตอบอื่นบรรลุผลได้อย่างไร @SeanLong
sehe

@SeanLong Right ดังนั้นผู้ใช้ต้องปฏิบัติตามคำสั่ง ดังนั้นคุณควรใส่อาร์กิวเมนต์ที่ต้องการมากที่สุดในอันดับแรก
Martin Braun

นี่เป็นตัวเลือกที่ง่ายที่สุดสำหรับฉัน ขอบคุณสำหรับการโพสต์ :)
Steve Bauman

3

การสร้างตัวแปรแบบไดนามิก

ใส่คำอธิบายภาพที่นี่

ข้อดี

  • ใช้ได้กับ> 9 อาร์กิวเมนต์
  • ช่วย%1, %2... %*ในชั้นเชิง
  • ใช้ได้ทั้ง/argกับ-argสไตล์
  • ไม่มีความรู้มาก่อนเกี่ยวกับข้อโต้แย้ง
  • การนำไปใช้งานแยกจากกิจวัตรหลัก

จุดด้อย

  • ข้อโต้แย้งเก่า ๆ อาจรั่วไหลไปสู่การวิ่งติดต่อกันดังนั้นควรใช้setlocalเพื่อกำหนดขอบเขตเฉพาะพื้นที่หรือเขียน:CLEAR-ARGSกิจวัตรประกอบ!
  • ไม่มีการสนับสนุนนามแฝง ๆ (เหมือน--forceจะ-f)
  • ไม่มี""การสนับสนุนอาร์กิวเมนต์ว่างเปล่า

การใช้งาน

นี่คือตัวอย่างว่าอาร์กิวเมนต์ต่อไปนี้เกี่ยวข้องกับตัวแปร. bat อย่างไร:

>> testargs.bat /b 3 -c /d /e /f /g /h /i /j /k /bar 5 /foo "c:\"

echo %*        | /b 3 -c /d /e /f /g /h /i /j /k /bar 5 /foo "c:\"
echo %ARG_FOO% | c:\
echo %ARG_A%   |
echo %ARG_B%   | 3
echo %ARG_C%   | 1
echo %ARG_D%   | 1

การนำไปใช้

@echo off
setlocal

CALL :ARG-PARSER %*

::Print examples
echo: ALL: %*
echo: FOO: %ARG_FOO%
echo: A:   %ARG_A%
echo: B:   %ARG_B%
echo: C:   %ARG_C%
echo: D:   %ARG_C%


::*********************************************************
:: Parse commandline arguments into sane variables
:: See the following scenario as usage example:
:: >> thisfile.bat /a /b "c:\" /c /foo 5
:: >> CALL :ARG-PARSER %*
:: ARG_a=1
:: ARG_b=c:\
:: ARG_c=1
:: ARG_foo=5
::*********************************************************
:ARG-PARSER
    ::Loop until two consecutive empty args
    :loopargs
        IF "%~1%~2" EQU "" GOTO :EOF

        set "arg1=%~1" 
        set "arg2=%~2"
        shift

        ::Allow either / or -
        set "tst1=%arg1:-=/%"
        if "%arg1%" NEQ "" (
            set "tst1=%tst1:~0,1%"
        ) ELSE (
            set "tst1="
        )

        set "tst2=%arg2:-=/%"
        if "%arg2%" NEQ "" (
            set "tst2=%tst2:~0,1%"
        ) ELSE (
            set "tst2="
        )


        ::Capture assignments (eg. /foo bar)
        IF "%tst1%" EQU "/"  IF "%tst2%" NEQ "/" IF "%tst2%" NEQ "" (
            set "ARG_%arg1:~1%=%arg2%"
            GOTO loopargs
        )

        ::Capture flags (eg. /foo)
        IF "%tst1%" EQU "/" (
            set "ARG_%arg1:~1%=1"
            GOTO loopargs
        )
    goto loopargs
GOTO :EOF


คุณยังสามารถย้ายเนื้อหาของ:ARG-PARSERรูทีนไปยังไฟล์. bat ภายนอกarg-parser.batเพื่อให้พร้อมใช้งานกับสคริปต์อื่น ๆ ได้เช่นกัน
Simon Streicher

1

เมื่อฉันเขียนโปรแกรมที่จัดการอาร์กิวเมนต์สั้น (-h) ยาว (--help) และไม่ใช่ตัวเลือกในไฟล์แบตช์ เทคนิคนี้รวมถึง:

  • อาร์กิวเมนต์ที่ไม่ใช่ตัวเลือกตามด้วยอาร์กิวเมนต์ตัวเลือก

  • ตัวดำเนินการเปลี่ยนสำหรับตัวเลือกที่ไม่มีอาร์กิวเมนต์เช่น '--help'

  • ตัวดำเนินการกะเวลาสองตัวสำหรับตัวเลือกที่ต้องการอาร์กิวเมนต์

  • วนซ้ำป้ายเพื่อประมวลผลอาร์กิวเมนต์บรรทัดคำสั่งทั้งหมด

  • ออกจากสคริปต์และหยุดการประมวลผลสำหรับตัวเลือกที่ไม่จำเป็นต้องมีการดำเนินการเพิ่มเติมเช่น '--help'

  • เขียนฟังก์ชั่นวิธีใช้เพื่อความสะดวกของผู้ใช้

นี่คือรหัสของฉัน

set BOARD=
set WORKSPACE=
set CFLAGS=
set LIB_INSTALL=true
set PREFIX=lib
set PROGRAM=install_boards

:initial
 set result=false
 if "%1" == "-h" set result=true
 if "%1" == "--help" set result=true
 if "%result%" == "true" (
 goto :usage
 )
 if "%1" == "-b" set result=true
 if "%1" == "--board" set result=true
 if "%result%" == "true" (
 goto :board_list
 )
 if "%1" == "-n" set result=true
 if "%1" == "--no-lib" set result=true
 if "%result%" == "true" (
 set LIB_INSTALL=false
 shift & goto :initial
 )
 if "%1" == "-c" set result=true
 if "%1" == "--cflag" set result=true
 if "%result%" == "true" (
 set CFLAGS=%2
 if not defined CFLAGS (
 echo %PROGRAM%: option requires an argument -- 'c'
 goto :try_usage
 )
 shift & shift & goto :initial
 )
 if "%1" == "-p" set result=true
 if "%1" == "--prefix" set result=true
 if "%result%" == "true" (
 set PREFIX=%2
 if not defined PREFIX (
 echo %PROGRAM%: option requires an argument -- 'p'
 goto :try_usage
 )
 shift & shift & goto :initial
 )

:: handle non-option arguments
set BOARD=%1
set WORKSPACE=%2

goto :eof


:: Help section

:usage
echo Usage: %PROGRAM% [OPTIONS]... BOARD... WORKSPACE
echo Install BOARD to WORKSPACE location.
echo WORKSPACE directory doesn't already exist!
echo.
echo Mandatory arguments to long options are mandatory for short options too.
echo   -h, --help                   display this help and exit
echo   -b, --boards                 inquire about available CS3 boards
echo   -c, --cflag=CFLAGS           making the CS3 BOARD libraries for CFLAGS
echo   -p. --prefix=PREFIX          install CS3 BOARD libraries in PREFIX
echo                                [lib]
echo   -n, --no-lib                 don't install CS3 BOARD libraries by default
goto :eof

:try_usage
echo Try '%PROGRAM% --help' for more information
goto :eof

1

นี่คือตัวแยกวิเคราะห์อาร์กิวเมนต์ คุณสามารถผสมอาร์กิวเมนต์สตริงใด ๆ (ไม่ถูกแตะต้อง) หรือตัวเลือกที่ใช้ Escape (คู่เดียวหรือตัวเลือก / ค่า) ในการทดสอบโดยไม่ใส่ข้อคิดเห็น 2 คำสั่งสุดท้ายและเรียกใช้เป็น:

getargs anystr1 anystr2 /test$1 /test$2=123 /test$3 str anystr3

Escape char หมายถึง"_SEP_=/"กำหนดนิยามใหม่หากจำเป็น

@echo off

REM Command line argument parser. Format (both "=" and "space" separators are supported):
REM   anystring1 anystring2 /param1 /param2=value2 /param3 value3 [...] anystring3 anystring4
REM Returns enviroment variables as:
REM   param1=1
REM   param2=value2
REM   param3=value3
REM Leading and traling strings are preserved as %1, %2, %3 ... %9 parameters
REM but maximum total number of strings is 9 and max number of leading strings is 8
REM Number of parameters is not limited!

set _CNT_=1
set _SEP_=/

:PARSE

if %_CNT_%==1 set _PARAM1_=%1 & set _PARAM2_=%2
if %_CNT_%==2 set _PARAM1_=%2 & set _PARAM2_=%3
if %_CNT_%==3 set _PARAM1_=%3 & set _PARAM2_=%4
if %_CNT_%==4 set _PARAM1_=%4 & set _PARAM2_=%5
if %_CNT_%==5 set _PARAM1_=%5 & set _PARAM2_=%6
if %_CNT_%==6 set _PARAM1_=%6 & set _PARAM2_=%7
if %_CNT_%==7 set _PARAM1_=%7 & set _PARAM2_=%8
if %_CNT_%==8 set _PARAM1_=%8 & set _PARAM2_=%9

if "%_PARAM2_%"=="" set _PARAM2_=1

if "%_PARAM1_:~0,1%"=="%_SEP_%" (
  if "%_PARAM2_:~0,1%"=="%_SEP_%" (
    set %_PARAM1_:~1,-1%=1
    shift /%_CNT_%
  ) else (
    set %_PARAM1_:~1,-1%=%_PARAM2_%
    shift /%_CNT_%
    shift /%_CNT_%
  )
) else (
  set /a _CNT_+=1
)

if /i %_CNT_% LSS 9 goto :PARSE

set _PARAM1_=
set _PARAM2_=
set _CNT_=

rem getargs anystr1 anystr2 /test$1 /test$2=123 /test$3 str anystr3
rem set | find "test$"
rem echo %1 %2 %3 %4 %5 %6 %7 %8 %9

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