คำตอบของ eplawlessสามารถแก้ปัญหาเฉพาะของเขาได้อย่างง่ายดายและมีประสิทธิภาพ: มันจะแทนที่"อินสแตนซ์ทั้งหมดในรายการอาร์กิวเมนต์ทั้งหมดด้วย\"ซึ่งเป็นวิธีที่ Bash ต้องการเครื่องหมายคำพูดคู่ภายในสตริงที่ยกมาสองครั้งเพื่อแสดง
โดยทั่วไปจะตอบคำถามเกี่ยวกับวิธีหลีกเลี่ยงเครื่องหมายอัญประกาศคู่ภายในสตริงที่ยกมาสองครั้งโดยใช้cmd.exeตัวแปลบรรทัดคำสั่งของ Windows (ไม่ว่าจะเป็นในบรรทัดคำสั่ง - มักจะเรียกผิดว่า "พรอมต์ DOS" หรือในไฟล์แบตช์): ดูด้านล่างสำหรับการดูที่PowerShell
tl; dr :
คุณต้องใช้""เมื่อส่งสตริงไปยังไฟล์แบตช์ (nother)และคุณสามารถใช้""กับแอปพลิเคชันที่สร้างด้วยคอมไพเลอร์ C / C ++ / NET ของ Microsoft (ซึ่งยอมรับเช่นกัน\" ) ซึ่งใน Windows รวมถึง Python และ Node.js :
\"ถูกต้อง - เป็นตัวเลือกเพียง - โดยโปรแกรมอื่น ๆ อีกมากมาย (! เช่นทับทิม, Perl, และแม้กระทั่งไมโครซอฟท์เอง Windows PowerShell ()) แต่การใช้งานเป็นไม่ปลอดภัย :
\"เป็นสิ่งที่โปรแกรมเรียกทำงานและตัวแปลจำนวนมากต้องการ - รวมถึง Windows PowerShell - เมื่อส่งผ่านสตริงจากภายนอก - หรือในกรณีของคอมไพเลอร์ของ Microsoft จะสนับสนุนเป็นทางเลือกอื่นใน ""ท้ายที่สุดแม้ว่าโปรแกรมเป้าหมายจะแยกวิเคราะห์รายการอาร์กิวเมนต์ .
- ตัวอย่าง:
foo.exe "We had 3\" of rain."
- อย่างไรก็ตามการใช้
\"สามารถส่งผลในการดำเนินการตามคำสั่งของอนุญาโตตุลาการโดยไม่ต้องการและ / หรือการเปลี่ยนทิศทางอินพุต / เอาต์พุต :
- อักขระต่อไปนี้แสดงความเสี่ยงนี้:
& | < >
- ตัวอย่างเช่นผลลัพธ์ต่อไปนี้ในการดำเนินการ
verคำสั่งโดยไม่ได้ตั้งใจ ดูเพิ่มเติมด้านล่างสำหรับคำอธิบายและสัญลักษณ์แสดงหัวข้อย่อยถัดไปสำหรับวิธีแก้ปัญหา:
foo.exe "3\" of snow" "& ver."
- สำหรับWindows PowerShell ,
\""และ"^""มีประสิทธิภาพ แต่ทางเลือก จำกัด (ดูส่วน "เรียก CLI PowerShell ของ ..." ด้านล่าง)
หากคุณต้องใช้\"มีเพียง 3 วิธีที่ปลอดภัยซึ่งเป็นวิธีที่ค่อนข้างยุ่งยาก : เคล็ดลับของหมวกสำหรับTSเพื่อขอความช่วยเหลือ
การใช้ (อาจเลือก ) ล่าช้าการขยายตัวของตัวแปรในแฟ้มชุดของคุณคุณสามารถเก็บอักษร\"ในตัวแปรและการอ้างอิงตัวแปรภายใน"..."สตริงโดยใช้!var!ไวยากรณ์ - ดูคำตอบที่เป็นประโยชน์ TS ของ
- วิธีการข้างต้นแม้จะยุ่งยาก แต่ก็มีข้อได้เปรียบที่คุณสามารถนำไปใช้ได้อย่างมีระบบและใช้งานได้ดีกับอินพุตใด ๆ
เฉพาะกับสตริงแบบ LITERAL เท่านั้นซึ่งไม่เกี่ยวข้องกับตัวแปร - คุณจะได้รับแนวทางที่เป็นระเบียบในทำนองเดียวกันหรือไม่: จัดหมวดหมู่^-escape ตัวละครทั้งหมด cmd.exe : " & | < >และ - หากคุณต้องการระงับการขยายตัวแปรด้วย - %:
foo.exe ^"3\^" of snow^" ^"^& ver.^"
มิฉะนั้นคุณต้องกำหนดสตริงของคุณโดยพิจารณาจากการรับรู้ว่าส่วนใดของสตริงที่cmd.exeพิจารณาว่าไม่ได้ใส่\"เครื่องหมายคำพูดเนื่องจากตีความผิดว่าเป็นตัวคั่นปิด:
ในส่วนที่เป็นตัวอักษรที่มีตัวอักษรเชลล์: ^-escape พวกเขา; จากตัวอย่างข้างต้นจะ&ต้องเป็น^-escaped:
foo.exe "3\" of snow" "^& ver."
ในส่วนที่มี%...%การอ้างอิงตัวแปรสไตล์ : ให้แน่ใจว่าcmd.exeจะพิจารณาเป็นส่วนหนึ่งของพวกเขา"..."สตริงและว่าค่าตัวแปรไม่ได้ว่าตัวเองมีการฝังตัว, คำพูดที่ไม่สมดุล - ซึ่งไม่ได้เป็นไปได้เสมอ
สำหรับข้อมูลพื้นฐานโปรดอ่านต่อ
พื้นหลัง
หมายเหตุ: นี่มาจากการทดลองของฉันเอง โปรดแจ้งให้ฉันทราบหากฉันผิด
เชลล์ที่เหมือน POSIX เช่น Bash บนระบบที่เหมือน Unix จะทำให้รายการอาร์กิวเมนต์ (สตริง) เป็นโทเค็นก่อนที่จะส่งอาร์กิวเมนต์ทีละรายการไปยังโปรแกรมเป้าหมาย: ในการขยายอื่น ๆ พวกเขาแยกรายการอาร์กิวเมนต์ออกเป็นแต่ละคำ (การแบ่งคำ) และลบอักขระการอ้างอิงออกจาก คำที่เป็นผลลัพธ์ (การลบใบเสนอราคา) โปรแกรมเป้าหมายที่ถูกส่งอาร์เรย์ของข้อโต้แย้งของแต่ละบุคคลด้วยประโยคคำพูดที่เอาออก
ในทางตรงกันข้ามตัวแปลคำสั่งของ Windows ดูเหมือนจะไม่โทเค็นรายการอาร์กิวเมนต์และเพียงแค่ส่งผ่านสตริงเดียวที่ประกอบด้วยอาร์กิวเมนต์ทั้งหมด - รวมถึงการอ้างอิงอักขระ - ไปยังโปรแกรมเป้าหมาย
อย่างไรก็ตามการประมวลผลล่วงหน้าบางอย่างเกิดขึ้นก่อนที่สตริงเดี่ยวจะถูกส่งผ่านไปยังโปรแกรมเป้าหมาย: ^Escape chars ภายนอกของสตริงที่ยกมาสองครั้งจะถูกลบออก (ซึ่งจะหลีกเลี่ยงอักขระต่อไปนี้) และการอ้างอิงตัวแปร (เช่น%USERNAME%) จะถูกแก้ไขก่อน
ดังนั้นไม่เหมือนใน Unix คือความรับผิดชอบของโปรแกรมเป้าหมายในการแยกวิเคราะห์เพื่อแยกวิเคราะห์สตริงอาร์กิวเมนต์และแยกย่อยออกเป็นอาร์กิวเมนต์แต่ละรายการโดยลบเครื่องหมายคำพูดออก ดังนั้นโปรแกรมที่แตกต่างกันอาจต้องการวิธีการหลบหนีที่แตกต่างกันโดยสมมุติฐานและไม่มีกลไกการหลบหนีเดียวที่รับประกันว่าจะทำงานกับทุกโปรแกรมได้ - https://stackoverflow.com/a/4094897/45375มีพื้นหลังที่ยอดเยี่ยมเกี่ยวกับอนาธิปไตยซึ่งเป็นบรรทัดคำสั่งของ Windows การแยกวิเคราะห์
ในทางปฏิบัติ\"เป็นเรื่องปกติมาก แต่ไม่ปลอดภัยดังที่กล่าวไว้ข้างต้น:
เนื่องจากcmd.exeตัวเองไม่ได้รับรู้\"เป็นหนีอ้างดับเบิลก็สามารถเข้าใจผิดในภายหลังสัญญาณในบรรทัดคำสั่งเป็นunquotedและอาจตีความว่าเป็นคำสั่งและ / หรืออินพุต / เอาต์พุตเปลี่ยนเส้นทาง
โดยสรุป: ปัญหาจะปรากฏขึ้นหากอักขระใด ๆ ต่อไปนี้เป็นไปตามการเปิดหรือไม่สมดุล \" :& | < > ; ตัวอย่างเช่น:
foo.exe "3\" of snow" "& ver."
cmd.exeเห็นโทเค็นต่อไปนี้ซึ่งเป็นผลมาจากการตีความผิด\"เป็นเครื่องหมายคำพูดคู่ปกติ:
"3\"
of
snow" "
- พักผ่อน:
& ver.
เนื่องจากcmd.exeคิดว่า& ver.ไม่มีเครื่องหมายอัญประกาศจึงตีความเป็น&(ตัวดำเนินการลำดับคำสั่ง) ตามด้วยชื่อของคำสั่งเพื่อดำเนินการ ( ver.- .ถูกละเว้นข้อมูลเวอร์ชันของverรายงานcmd.exe)
ผลกระทบโดยรวมคือ:
- ขั้นแรก
foo.exeถูกเรียกใช้ด้วยโทเค็น3 ตัวแรกเท่านั้น
- จากนั้นคำสั่ง
verจะถูกดำเนินการ
แม้ในกรณีที่คำสั่งโดยไม่ได้ตั้งใจไม่เป็นอันตราย แต่คำสั่งโดยรวมของคุณจะไม่ทำงานตามที่ออกแบบไว้เนื่องจากไม่ได้ส่งผ่านอาร์กิวเมนต์ทั้งหมดไป
คอมไพเลอร์ / ล่ามจำนวนมากรู้จักเฉพาะ\" - เช่นคอมไพเลอร์ GNU C / C ++, Python, Perl, Ruby แม้กระทั่ง Windows PowerShell ของ Microsoft เองเมื่อเรียกใช้จากcmd.exe- และยกเว้น (มีข้อ จำกัด ) สำหรับ Windows PowerShell ด้วย\""สำหรับพวกเขาไม่มีวิธีง่ายๆ กับปัญหานี้
โดยพื้นฐานแล้วคุณจะต้องรู้ล่วงหน้าว่าส่วนใดของบรรทัดคำสั่งของคุณถูกตีความผิดว่าไม่มีการ^อ้างถึงและเลือก - คัดลอกอินสแตนซ์ทั้งหมด& | < >ในส่วนเหล่านั้น
ในทางตรงกันข้ามการใช้งาน""คือ SAFEแต่น่าเสียดายที่ได้รับการสนับสนุนโดยไฟล์ปฏิบัติการและไฟล์แบตช์ที่ใช้คอมไพเลอร์ของ Microsoft เท่านั้น (ในกรณีของไฟล์แบตช์ที่มีลักษณะไม่ชอบมาพากลที่กล่าวถึงข้างต้น) ซึ่งโดดเด่นไม่รวมPowerShell - ดูหัวข้อถัดไป
การเรียก CLI ของ PowerShell จากcmd.exeหรือเชลล์แบบ POSIX:
หมายเหตุ: ดูส่วนด้านล่างสำหรับวิธีจัดการใบเสนอราคาภายใน PowerShell
เมื่อเรียกใช้จากภายนอก - เช่นจากcmd.exeไม่ว่าจะจากบรรทัดคำสั่งหรือแบตช์ไฟล์:
PowerShell [หลัก] v6 +ตอนนี้ต้องตระหนัก"" (นอกเหนือ\") ซึ่งเป็นทั้งความปลอดภัยในการใช้งานและช่องว่างการรักษา
pwsh -c " ""a & c"".length " ไม่แตกและให้ผลผลิตอย่างถูกต้อง 6
Windows PowerShell (รุ่นดั้งเดิมที่มีเวอร์ชันล่าสุดคือ 5.1) จะ รับรู้เท่านั้น \"และใน Windows ด้วย"""และยิ่งมีประสิทธิภาพมากขึ้น\""/"^"" (แม้ว่าPowerShellภายในจะใช้`เป็นอักขระหลีกในสตริงที่ยกมาสองครั้งและยังยอมรับ""- ดูส่วนด้านล่าง):
การเรียกWindows PowerShell จากcmd.exe / ไฟล์แบตช์:
"" หยุดพักเนื่องจากไม่ได้รับการสนับสนุนโดยพื้นฐาน:
powershell -c " ""ab c"".length " -> ข้อผิดพลาด "สตริงไม่มีตัวยุติ"
\"และ""" ทำงานตามหลักการแต่ไม่ปลอดภัย :
powershell -c " \"ab c\".length "ทำงานตามที่ตั้งใจไว้: เอาต์พุต5(สังเกต2ช่องว่าง)
- แต่มันไม่ปลอดภัยเพราะ
cmd.exemetacharacters ทำลายคำสั่งเว้นแต่จะ Escape:
powershell -c " \"a& c\".length " หยุดพักเนื่องจากสิ่ง&ที่จะต้องหนีในฐานะ^&
\""เป็นที่ปลอดภัยแต่การตกแต่งภายในปกติช่องว่างซึ่งสามารถที่ไม่พึงประสงค์:
powershell -c " \""a& c\"".length "เอาต์พุต4(!) เนื่องจากช่องว่าง 2 ช่องถูกทำให้เป็นมาตรฐานเป็น 1
"^""เป็นตัวเลือกที่ดีที่สุดสำหรับการWindows PowerShellโดยเฉพาะซึ่งจะมีทั้งความปลอดภัยและช่องว่างการรักษา แต่กับ PowerShell หลัก (ใน Windows) มันเป็นเช่นเดียวกับ\""คือด้วยช่องว่างnormalizing เครดิตไปที่Venryxสำหรับการค้นพบแนวทางนี้
powershell -c " "^""a& c"^"".length " ผลงาน : ไม่แตก - แม้จะ&- และผลลัพธ์5คือช่องว่างที่เก็บรักษาไว้อย่างถูกต้อง
PowerShell หลัก : pwsh -c " "^""a& c"^"".length " ทำงานแต่ผล4คือNormalizes ช่องว่างเป็น\""ไม่
บนแพลตฟอร์มที่เหมือน Unix (Linux, macOS) เมื่อเรียกใช้CLI ของPowerShell [Core]pwshจากเชลล์ที่คล้าย POSIX เช่นbash:
คุณต้องใช้\"อย่างไรก็ตามทั้งปลอดภัยและรักษาช่องว่าง :
$ pwsh -c " \"a& c|\".length"
ข้อมูลที่เกี่ยวข้อง
^เท่านั้นที่สามารถนำมาใช้เป็นตัวหนีในunquotedสตริง - สตริงภายในสองครั้งที่ยกมา^เป็นพิเศษและไม่ถือว่าเป็นตัวอักษร
- CAVEAT : การใช้
^ในพารามิเตอร์ที่ส่งผ่านไปยังcallคำสั่งนั้นใช้ไม่ได้ (ใช้กับทั้งการใช้call: การเรียกใช้ไฟล์แบตช์หรือไบนารีอื่นและการเรียกรูทีนย่อยในไฟล์แบตช์เดียวกัน):
^กรณียกมาสองครั้งค่าเท่าตัวลึกลับเปลี่ยนแปลงมูลค่าที่ถูกส่ง: เช่นถ้าตัวแปร%v%มีค่าที่แท้จริงa^b, call :foo "%v%"กำหนด"a^^b"ที่จะ (!) %1(พารามิเตอร์แรก) :fooในย่อย
- unquotedใช้
^กับcallจะเสียโดยสิ้นเชิงในการที่^จะไม่สามารถใช้ในการหลบหนีตัวอักษรพิเศษ : เช่นcall foo.cmd a^&bเงียบ ๆ แบ่ง (แทนการส่งผ่านตัวอักษรa&bมากเกินไปfoo.cmdเช่นจะเป็นกรณีที่โดยไม่ต้องcall) -foo.cmdไม่เคยเรียกแม้อย่างน้อยบน Windows (!) 7.
การหลีกเลี่ยงลิเทอรัล%เป็นกรณีพิเศษน่าเสียดายที่ต้องใช้ไวยากรณ์ที่แตกต่างกันขึ้นอยู่กับว่าสตริงถูกระบุในบรรทัดคำสั่งเทียบกับภายในไฟล์แบตช์หรือไม่ ดูhttps://stackoverflow.com/a/31420292/45375
- สั้น ๆ : ภายในไฟล์แบตช์ให้ใช้
%%. ในบรรทัดคำสั่งที่%ไม่สามารถหนีออกมา แต่ถ้าคุณวาง^ที่เริ่มต้นสิ้นสุดหรือภายในชื่อตัวแปรในunquotedสตริง (เช่นecho %^foo%) คุณสามารถป้องกันไม่ให้เกิดการขยายตัวของตัวแปร (แก้ไข); %อินสแตนซ์บนบรรทัดคำสั่งที่ไม่ได้เป็นส่วนหนึ่งของการอ้างอิงตัวแปรจะถือว่าเป็นตัวอักษร (เช่น100%)
โดยทั่วไปในการทำงานอย่างปลอดภัยกับค่าตัวแปรที่อาจมีช่องว่างและอักขระพิเศษ :
- ที่ได้รับมอบหมาย : แนบทั้งชื่อตัวแปรและความคุ้มค่าในที่เดียวคู่ของราคาสองครั้ง ; เช่น
set "v=a & b"กำหนดค่าตามตัวอักษรa & bให้กับตัวแปร%v%(ในทางตรงกันข้ามset v="a & b"จะทำให้เครื่องหมายคำพูดคู่เป็นส่วนหนึ่งของค่า) หลีกเลี่ยง%อินสแตนซ์ตามตัวอักษรเป็น%%(ใช้ได้เฉพาะในไฟล์แบตช์ - ดูด้านบน)
- การอ้างอิง : การอ้างอิงตัวแปร double-quoteเพื่อให้แน่ใจว่าค่าของพวกเขาไม่ได้ถูกแก้ไข เช่น
echo "%v%"ไม่อยู่ภายใต้ค่าของ%v%การแก้ไขและการพิมพ์"a & b"(แต่โปรดทราบว่าเครื่องหมายคำพูดคู่จะถูกพิมพ์อย่างสม่ำเสมอด้วย) โดยคมชัดecho %v%ผ่านตัวอักษรaที่จะechoตำเป็นผู้ประกอบการลำดับคำสั่งและดังนั้นจึงพยายามที่จะดำเนินการคำสั่งที่มีชื่อว่า&
โปรดสังเกตข้อแม้ข้างต้นที่ใช้ซ้ำกับคำสั่งb
^call
- โดยทั่วไปโปรแกรมภายนอกจะดูแลการลบเครื่องหมายอัญประกาศคู่รอบพารามิเตอร์ แต่ตามที่ระบุไว้ในไฟล์แบตช์คุณต้องทำด้วยตัวเอง (เช่น
%~1เพื่อลบการปิดเครื่องหมายอัญประกาศคู่ออกจากพารามิเตอร์ที่ 1) และน่าเศร้าที่ไม่มีโดยตรง วิธีที่ฉันรู้ที่จะได้รับechoการพิมพ์ค่าตัวแปรนับถือโดยไม่ต้องล้อมรอบราคาสองครั้ง
- นีลมีวิธีแก้ปัญหาชั่นว่างานตราบเท่าที่คุ้มค่าได้ฝังไม่มีคำพูดสอง ; เช่น:
for
set "var=^&')|;,%!"
for /f "delims=" %%v in ("%var%") do echo %%~v
cmd.exeไม่ได้รับรู้เดียว -quotesเป็นตัวคั่นสตริง - พวกเขาจะถือว่าเป็นตัวอักษรและไม่สามารถโดยทั่วไปจะใช้ในการสตริงคั่นด้วยช่องว่างฝัง; นอกจากนี้ยังเป็นไปตามที่โทเค็นที่ติดเครื่องหมายคำพูดเดี่ยวและโทเค็นใด ๆ ที่อยู่ระหว่างนั้นจะถือว่าไม่มีการอ้างสิทธิ์cmd.exeและตีความตามนั้น
- อย่างไรก็ตามเนื่องจากโปรแกรมเป้าหมายดำเนินการแยกวิเคราะห์อาร์กิวเมนต์ของตนเองในท้ายที่สุดโปรแกรมบางโปรแกรมเช่น Ruby จะรู้จักสตริงที่มีเครื่องหมายอัญประกาศเดี่ยวแม้ใน Windows ในทางตรงกันข้ามไฟล์ปฏิบัติการ C / C ++, Perl และ Python ไม่รู้จักสิ่งเหล่านี้
แม้ว่าได้รับการสนับสนุนโดยโปรแกรมเป้าหมาย cmd.exeแต่ก็ไม่แนะนำให้ใช้สายเดียวที่ยกมาระบุว่าเนื้อหาของพวกเขาจะไม่ได้รับการคุ้มครองจากการตีความที่ไม่พึงประสงค์ที่อาจเกิดขึ้นโดย
การอ้างอิงจากภายใน PowerShell:
Windows PowerShellเป็นเชลล์ขั้นสูงกว่าcmd.exeมากและเป็นส่วนหนึ่งของ Windows มาหลายปีแล้ว (และPowerShell Coreก็นำประสบการณ์ PowerShell มาสู่ macOS และ Linux เช่นกัน)
PowerShell ทำงานภายในอย่างสม่ำเสมอเกี่ยวกับการอ้างถึง:
- ภายในสตริงที่ยกมาคู่ใช้
`"หรือ""เพื่อหลีกเลี่ยงเครื่องหมายอัญประกาศคู่
- ภายในสตริงที่ยกมาเดี่ยวใช้
''เพื่อหลีกเลี่ยงเครื่องหมายคำพูดเดี่ยว
สิ่งนี้ใช้ได้กับบรรทัดคำสั่ง PowerShell และเมื่อส่งผ่านพารามิเตอร์ไปยังสคริปต์หรือฟังก์ชันPowerShell จากภายใน PowerShell
(ดังที่ได้กล่าวไว้ข้างต้นการส่งคำพูดคู่ที่ใช้ Escape ไปยัง PowerShell จากภายนอกต้องใช้\"หรือมีประสิทธิภาพมากขึ้น\""- ไม่มีอะไรทำงานได้อีก)
น่าเศร้าเมื่อเรียกใช้โปรแกรมภายนอกจาก PowerShell คุณต้องเผชิญกับความจำเป็นในการรองรับกฎการอ้างสิทธิ์ของ PowerShell และเพื่อหลีกเลี่ยงโปรแกรมเป้าหมาย :
พฤติกรรมที่เป็นปัญหานี้จะกล่าวถึงและสรุปไว้ในคำตอบนี้ด้วย
Double -quotes ภายในสตริงdouble -quoted :
พิจารณาสตริง"3`" of rain"ซึ่ง 3" of rainPowerShell-ภายในแปลเป็นตัวอักษร
หากคุณต้องการส่งสตริงนี้ไปยังโปรแกรมภายนอกคุณต้องใช้การหลบหนีของโปรแกรมเป้าหมายเพิ่มเติมจาก PowerShell's ; สมมติว่าคุณต้องการส่งสตริงไปยังโปรแกรม C ซึ่งคาดว่าเครื่องหมายคำพูดคู่ที่ฝังไว้จะถูก Escape เป็น\":
foo.exe "3\`" of rain"
หมายเหตุวิธีการทั้งสอง `" - เพื่อให้มีความสุข PowerShell - และ\ - เพื่อให้มีความสุขโปรแกรมเป้าหมาย - จะต้องนำเสนอ
ตรรกะเดียวกันนี้ใช้กับการเรียกไฟล์แบตช์โดยที่""ต้องใช้:
foo.bat "3`"`" of rain"
ในทางตรงกันข้ามการฝังsingle -quotes ในสตริงdouble -quotedไม่จำเป็นต้องมีการหลบหนีเลย
โสด -quotes ภายในเดียวสตริง -quotedไม่ไม่จำเป็นต้องเสริมหลบหนี; พิจารณา'2'' of snow'ซึ่งเป็นตัวแทน PowerShell 2' of snowของ
foo.exe '2'' of snow'
foo.bat '2'' of snow'
PowerShell แปลสตริงที่ยกมาเดี่ยวเป็นสตริงที่ยกมาสองครั้งก่อนที่จะส่งต่อไปยังโปรแกรมเป้าหมาย
อย่างไรก็ตามdouble -quotes ภายในสตริงsingle -quotedซึ่งไม่จำเป็นต้องมีการ Escape สำหรับPowerShellยังคงต้องมีการ Escape สำหรับโปรแกรมเป้าหมาย :
foo.exe '3\" of rain'
foo.bat '3"" of rain'
PowerShell v3แนะนำ--%ตัวเลือกเวทย์มนตร์ที่เรียกว่าสัญลักษณ์หยุดการแยกวิเคราะห์ซึ่งช่วยบรรเทาความเจ็บปวดบางอย่างโดยการส่งผ่านอะไรก็ได้หลังจากที่ไม่ได้ตีความไปยังโปรแกรมเป้าหมายบันทึกcmd.exeการอ้างอิงตัวแปรสภาพแวดล้อม - style (เช่น%USERNAME%) ซึ่งจะขยาย; เช่น:
foo.exe --% "3\" of rain" -u %USERNAME%
หมายเหตุวิธีหนีฝังตัว"เป็น\"โปรแกรมเป้าหมายเท่านั้น (และไม่ยัง PowerShell เป็น\`") ก็เพียงพอแล้ว
อย่างไรก็ตามแนวทางนี้:
- ไม่อนุญาตให้มีการหลีกเลี่ยง
%อักขระเพื่อหลีกเลี่ยงการขยายตัวแปรสภาพแวดล้อม
- ห้ามการใช้ตัวแปรและนิพจน์ PowerShell โดยตรง แทนที่จะสร้างบรรทัดคำสั่งในตัวแปรสตริงในขั้นตอนแรกจากนั้นเรียกใช้
Invoke-Expressionในวินาที
ดังนั้นแม้จะมีความก้าวหน้ามากมาย แต่ PowerShell ก็ไม่ได้ทำให้การหลบหนีง่ายขึ้นเมื่อเรียกโปรแกรมภายนอก อย่างไรก็ตามมีการแนะนำการสนับสนุนสำหรับสตริงที่ยกมาเดี่ยว
ผมสงสัยว่ามันเป็นไปได้ที่ลึกซึ้งในโลกของ Windows เพื่อสลับเคยไปแบบ Unix ของการปล่อยให้เปลือกทำทุก tokenization และอ้างการกำจัดที่ไม่คาดฝัน , ขึ้นด้านหน้า , โดยไม่คำนึงถึงโปรแกรมเป้าหมายและจากนั้นเรียกใช้โปรแกรมเป้าหมายโดยผ่านราชสกุลที่เกิด .