มีวิธีการที่หลีกเลี่ยง^
ลำดับการหลบหนี
คุณสามารถใช้ตัวแปรที่มีการขยายล่าช้า ด้านล่างนี้เป็นการสาธิตสคริปต์ชุดเล็ก ๆ
@echo off
setlocal enableDelayedExpansion
set "line=<html>"
echo !line!
หรือคุณสามารถใช้ลูป FOR / F จากบรรทัดคำสั่ง:
for /f "delims=" %A in ("<html>") do @echo %~A
หรือจากชุดสคริปต์:
@echo off
for /f "delims=" %%A in ("<html>") do echo %%~A
เหตุผลเหล่านี้วิธีการทำงานเป็นเพราะการขยายตัวทั้งล่าช้าและสำหรับการขยายตัวตัวแปรเกิดขึ้นหลังจากที่ผู้ประกอบการพิเศษเช่น<
, >
, &
, |
, &&
, ||
มีการแยกวิเคราะห์ ดูว่า Windows Command Interpreter (CMD.EXE) แยกวิเคราะห์สคริปต์อย่างไร สำหรับข้อมูลเพิ่มเติม
sin3.14 ชี้ให้เห็นว่าท่ออาจต้องการการหลบหนีหลายครั้ง ตัวอย่างเช่น:
echo ^^^<html^^^>|findstr .
สาเหตุที่ไปป์ต้องการการหลบหนีหลายครั้งเนื่องจากแต่ละด้านของไปป์ถูกดำเนินการในกระบวนการ CMD ใหม่ดังนั้นบรรทัดจึงถูกแยกวิเคราะห์หลายครั้ง ดูเหตุใดการขยายล่าช้าจึงล้มเหลวเมื่ออยู่ในบล็อกโค้ดที่ถูกส่งไป สำหรับคำอธิบายของผลที่น่าอึดอัดใจมากมายจากการใช้งานท่อของ Window
มีอีกวิธีหนึ่งในการหลีกเลี่ยงการหนีหลายครั้งเมื่อใช้ท่อ คุณสามารถสร้างอินสแตนซ์ของกระบวนการ CMD ของคุณเองอย่างชัดเจนและป้องกันการหลีกเลี่ยงรายการเดียวด้วยเครื่องหมายคำพูด:
cmd /c "echo ^<html^>"|findstr .
หากคุณต้องการใช้เทคนิคการขยายที่ล่าช้าเพื่อหลีกเลี่ยงการหลบหนีมีเรื่องที่น่าประหลาดใจยิ่งกว่านั้น (คุณอาจไม่แปลกใจถ้าคุณเป็นผู้เชี่ยวชาญในการออกแบบ CMD.EXE แต่ไม่มีเอกสาร MicroSoft ที่อธิบายถึงสิ่งนี้อย่างเป็นทางการ)
โปรดจำไว้ว่าแต่ละด้านของไปป์ได้รับการดำเนินการในกระบวนการ CMD.EXE ของตัวเอง แต่กระบวนการนี้ไม่ได้รับช่วงสถานะการขยายล่าช้าซึ่งจะมีค่าเริ่มต้นเป็น OFF ดังนั้นคุณต้องสร้างอินสแตนซ์กระบวนการ CMD.EXE ของคุณเองอย่างชัดเจนและใช้ตัวเลือก / V: ON เพื่อเปิดใช้งานการขยายที่ล่าช้า
@echo off
setlocal disableDelayedExpansion
set "line=<html>"
cmd /v:on /c echo !test!|findstr .
โปรดทราบว่าการขยายล่าช้าปิดอยู่ในสคริปต์แบตช์หลัก
แต่นรกทั้งหมดจะหลุดออกไปหากเปิดใช้งานการขยายล่าช้าในสคริปต์หลัก สิ่งต่อไปนี้ใช้ไม่ได้ :
@echo off
setlocal enableDelayedExpansion
set "line=<html>"
REM - the following command fails
cmd /v:on /c echo !test!|findstr .
ปัญหาคือว่า!test!
จะขยายตัวในสคริปต์ผู้ปกครองเพื่อให้กระบวนการ CMD ใหม่พยายามที่จะแยกที่ไม่มีการป้องกันและ<
>
คุณสามารถหลบหนีได้!
แต่อาจเป็นเรื่องยุ่งยากเพราะมันขึ้นอยู่กับว่า!
มีการยกมาหรือไม่
หากไม่ได้ยกมาจำเป็นต้องมีการหลบหนีสองครั้ง:
@echo off
setlocal enableDelayedExpansion
set "line=<html>"
cmd /v:on /c echo ^^!test^^!|findstr .
หากยกมาจะใช้การหลบหนีเดียว:
@echo off
setlocal enableDelayedExpansion
set "line=<html>"
cmd /v:on /c "echo ^!test^!"|findstr .
แต่มีเคล็ดลับที่น่าประหลาดใจที่หลีกเลี่ยงการหลบหนีทั้งหมด - การปิดด้านซ้ายของไปป์จะป้องกันไม่ให้สคริปต์พาเรนต์ขยาย!test!
ก่อนเวลาอันควร:
@echo off
setlocal enableDelayedExpansion
set "line=<html>"
(cmd /v:on /c echo !test!)|findstr .
แต่ฉันคิดว่าแม้ว่านั่นจะไม่ใช่อาหารกลางวันฟรีเพราะตัวแยกวิเคราะห์แบตช์จะแนะนำช่องว่างเพิ่มเติม (อาจไม่ต้องการ) ในตอนท้ายเมื่อใช้วงเล็บ
Aint batch scripting fun ;-)