หลบหนีวงเล็บมุมในพรอมต์คำสั่งของ Windows


95

ฉันต้องการสะท้อนสตริงที่มีวงเล็บมุม (<และ>) ไปยังไฟล์บนเครื่อง Windows โดยทั่วไปสิ่งที่ฉันต้องการทำมีดังต่อไปนี้:
echo some string < with angle > brackets >>myfile.txt

สิ่งนี้ใช้ไม่ได้เนื่องจากตัวแปลคำสั่งสับสนกับวงเล็บมุม ฉันสามารถอ้างถึงสตริงทั้งหมดได้ดังนี้:
echo "some string < with angle > brackets" >>myfile.txt

แต่แล้วฉันมีเครื่องหมายคำพูดคู่ในไฟล์ที่ฉันไม่ต้องการ

การหลีกเลี่ยงวงเล็บ ala unix ใช้ไม่ได้:
echo some string \< with angle \> brackets >>myfile.txt

ไอเดีย?


6
คำพูดจะถูกสะท้อนด้วย
dalle

คำตอบ:


172

อักขระ Escape ของ Windows คือ ^ ด้วยเหตุผลบางประการ

echo some string ^< with angle ^> brackets >>myfile.txt

10
แบ็กสแลชใช้สำหรับชื่อพา ธ และเครื่องหมายคำพูดคู่คือการตัดชื่อไฟล์ที่มีช่องว่างดังนั้นจึงเหลือตัวเลือกอักขระไม่มาก
James Curran

สิ่งนี้ใช้ได้กับอักขระอื่น ๆ เช่นเครื่องหมายและ (&) ด้วยขอบคุณ
tenfour

2
ใช้งานได้ดี! echo some string ^< with angle ^> brackets >>conผลลัพธ์ใน: วงเล็บ <พร้อมมุม> บางส่วน
Ross Bradbury

1
ทั้งหมดเป็นเพราะพีซีดอสดั้งเดิมใช้แบ็กสแลชสำหรับพา ธ และความเข้ากันได้ย้อนหลัง
Jahmic

ฉันสงสัยว่ามันไม่ใช่แบบสุ่มทั้งหมด ฉันเดาว่าพวกเขาต้องการใช้อักขระที่ไม่น่าจะปรากฏในข้อความปกติเพื่อไม่ให้อักขระที่หลีกเลี่ยงได้ง่าย แต่ไม่ต้องการหลบหนี
David

25

จริงอยู่อักขระหนีอย่างเป็นทางการคือ^แต่ระวังเพราะบางครั้งคุณต้องใช้อักขระสาม ^ตัว นี่เป็นเพียงบางครั้ง :

C:\WINDOWS> echo ^<html^>
<html>

C:\WINDOWS> echo ^<html^> | sort
The syntax of the command is incorrect.

C:\WINDOWS> echo ^^^<html^^^> | sort
<html>

C:\WINDOWS> echo ^^^<html^^^>
^<html^>

เคล็ดลับอย่างหนึ่งจากเรื่องไร้สาระนี้คือการใช้คำสั่งอื่นนอกเหนือจากechoการทำผลลัพธ์และอ้างด้วยเครื่องหมายคำพูดคู่

C:\WINDOWS> set/p _="<html>" <nul
<html>
C:\WINDOWS> set/p _="<html>" <nul | sort
<html>

โปรดทราบว่าสิ่งนี้จะไม่รักษาช่องว่างนำหน้าในข้อความแจ้ง


2
ดูส่วนที่ 2 ของคำตอบของฉันสำหรับคำอธิบายว่าทำไมไปป์จึงต้องมีการหลบหนีหลายตัว
dbenham

1
ทั้งสาม^^^ยังจำเป็นในการหลีกเลี่ยงคำสั่งในคอนโซล Azure DOS / Kudu
lionello

ฉันพบว่าสิ่งนี้จำเป็นอย่างยิ่งเมื่อคุณต้องการจัดเก็บค่าที่มีเครื่องหมายวงเล็บแหลมใน Azure keyvault ผ่าน Azure CLI
Jaap

8

มีวิธีการที่หลีกเลี่ยง^ลำดับการหลบหนี

คุณสามารถใช้ตัวแปรที่มีการขยายล่าช้า ด้านล่างนี้เป็นการสาธิตสคริปต์ชุดเล็ก ๆ

@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 ;-)


3

ในการใช้อักขระพิเศษเช่น ">" บน Windows พร้อมเสียงสะท้อนคุณต้องวางอักขระหลีกพิเศษไว้ข้างหน้า

ตัวอย่างเช่น

echo A->B

จะไม่ทำงานเนื่องจาก ">" จะต้องถูกหลีกเลี่ยงโดย "^":

 echo A-^>B

ดูลำดับการหลบหนีด้วย ป้อนคำอธิบายภาพที่นี่

มีไฟล์แบตช์สั้น ๆ ซึ่งพิมพ์ชุดอักขระพิเศษพื้นฐานและลำดับการหลบหนี


0

การหลีกเลี่ยงวงเล็บ ala unix ใช้ไม่ได้:

สะท้อนสตริง \ <พร้อมมุม \> วงเล็บ >> myfile.txt

แบ็กสแลชจะถือเป็นจุดเริ่มต้นของชื่อพา ธ สัมบูรณ์


2
ชื่อพา ธ สัมบูรณ์สัมพันธ์กับอักษรระบุไดรฟ์ปัจจุบัน ... ;)
dalle

เครื่องหมายแบ็กสแลชไม่ถือเป็นจุดเริ่มต้นของชื่อพา ธ สัมบูรณ์ภายในข้อความสำหรับคำสั่ง echo แต่เป็นเพียงข้อความธรรมดาที่ถูกส่งไปที่ใดก็ตามที่คุณส่ง - echo \ ตัวอย่างเช่นทำงานได้ตามที่คาดไว้ - แต่ใช่ "\" จะเป็นตัวเลือกที่ไม่ดีสำหรับอักขระหลีกบรรทัดคำสั่งเนื่องจากทุกคำสั่ง / โปรแกรมที่ต้องการพา ธ หรือชื่อไฟล์คุณจะต้องพิมพ์ `\` แทน
BrainSlugs83

1
คำตอบนี้ไม่ได้เสนอวิธีแก้ปัญหาสำหรับคำถามที่คลุมเครือซึ่งเป็นที่ยอมรับ
G-

-3

คุณยังสามารถใช้เครื่องหมายคำพูดคู่เพื่อหลีกเลี่ยงอักขระพิเศษ ...

echo some string "<" with angle ">" brackets >>myfile.txt

5
ที่ไม่ได้ผล echo some string "<" with angle ">" brackets >>conผลลัพธ์ใน: วงเล็บสตริง "<" with angle ">"แต่ OP ต้องการวงเล็บ <with angle>
Ross Bradbury
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.