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


14

ใน Bash เมื่อระบุอาร์กิวเมนต์บรรทัดคำสั่งให้กับคำสั่งจำเป็นต้องใช้อักขระใดในการหลีกเลี่ยง

พวกเขาจะถูก จำกัด ให้ metacharacters ของทุบตี: พื้นที่แท็บ |, &, ;, (, ), <และ>?


อย่าลืมชื่อไฟล์ที่เป็นไปได้ที่มี * และ?
Jeff Schaller

ขอบคุณ คุณช่วยระบุประเภทของตัวละครที่ต้องหลบหนีในแถว cmd ได้หรือไม่?
ทิม

รายการเป็นสิ่งที่ดีที่จะมี แต่สิ่งที่สำคัญที่สุดที่ต้องเข้าใจเกี่ยวกับการอ้างอิงคือ: ทุกสิ่งระหว่างคำพูดเดียวจะถูกส่งผ่านตัวอักษรและไม่มีการแยกคำ ไม่มีข้อยกเว้น. (ซึ่งหมายความว่าไม่มีทางใด ๆ ที่จะฝังคำพูดเดียวในคำพูดเดียวโดยวิธี แต่วิธีที่ง่ายต่อการทำงาน .)
Wildcard

คำตอบ:


22

อักขระต่อไปนี้มีความหมายพิเศษต่อเชลล์เองในบางบริบทและอาจจำเป็นต้องมีการหลบหนีในอาร์กิวเมนต์:

ตัวละครเหล่านี้บางตัวใช้สำหรับสิ่งต่าง ๆ และในที่มากกว่าตัวละครที่ฉันเชื่อมโยง


มีบางกรณีที่มีมุมที่เป็นทางเลือกอย่างชัดเจน:

  • !สามารถปิดการใช้งานด้วยset +Hซึ่งเป็นค่าเริ่มต้นในเปลือกไม่ใช่แบบโต้ตอบ
  • {set +Bสามารถใช้งานกับ
  • *และ?สามารถใช้งานด้วยหรือset -fset -o noglob
  • =เครื่องหมายเท่ากับ (U + 003D) ต้องมีการหลีกหนีหากเปิดใช้งานset -kหรือset -o keywordเปิดใช้งาน

การขึ้นบรรทัดใหม่ต้องใช้การอ้างอิง - แบ็กสแลชจะไม่ทำงาน ตัวละครอื่น ๆ ที่ระบุในIFSจะต้องมีการจัดการที่คล้ายกัน คุณไม่จำเป็นที่จะหลบหนี]หรือ}แต่คุณไม่จำเป็นต้องหนี)เพราะมันเป็นผู้ดำเนินการ

ตัวละครเหล่านี้บางตัวมีข้อ จำกัด ที่เข้มงวดมากขึ้นเมื่อพวกเขาต้องการหลบหนีอย่างแท้จริง ตัวอย่างเช่นa#bก็โอเค แต่a #bเป็นความคิดเห็นในขณะที่>จะต้องหลบหนีในบริบททั้งสอง มันไม่เจ็บที่จะหลบหนีพวกเขาอย่างอนุรักษ์นิยมทั้งหมดและมันง่ายกว่าจดจำความแตกต่างที่ดี

ถ้าชื่อคำสั่งของคุณเองเป็นคำหลักเปลือก ( if, for, do) แล้วคุณจะต้องหลบหนีหรือพูดมันมากเกินไป สิ่งที่น่าสนใจเพียงอย่างเดียวคือinเพราะมันไม่ชัดเจนว่าเป็นคำหลักเสมอ คุณไม่จำเป็นต้องทำเช่นนั้นสำหรับคำหลักที่ใช้ในการโต้แย้งเฉพาะเมื่อคุณ (โง่เขลา!) ​​ตั้งชื่อคำสั่งหลังจากหนึ่งในนั้น ตัวดำเนินการเชลล์ ( (, &ฯลฯ ) จำเป็นต้องมีการอ้างอิงทุกที่


1 Stéphaneตั้งข้อสังเกตว่าอักขระว่างไบต์เดียวอื่น ๆจากโลแคลของคุณต้องหลบหนี ในสถานที่ที่พบเห็นได้ทั่วไปส่วนใหญ่อย่างน้อยที่อยู่บนพื้นฐานของ C หรือ UTF-8 เป็นเพียงอักขระช่องว่างด้านบน ในที่ตั้ง ISO-8859-1 บางพื้นที่ U + 00A0 ไม่มีการหยุดพักถือว่าว่างเปล่ารวมถึง Solaris, BSDs และ OS X (ฉันคิดว่าไม่ถูกต้อง) หากคุณกำลังจัดการกับสถานที่ที่ไม่รู้จักโดยพลการมันอาจรวมถึงอะไรก็ได้รวมถึงตัวอักษรโชคดีมาก

น่าจะเป็นไบต์เดียวที่พิจารณาว่าว่างเปล่าอาจปรากฏขึ้นในตัวละครหลายไบต์ที่ไม่ได้ว่างเปล่าและคุณไม่มีทางที่จะหลบหนีไปได้นอกจากการใส่ทุกอย่างไว้ในเครื่องหมายคำพูด นี่ไม่ใช่ข้อกังวลทางทฤษฎี: ในโลแคล ISO-8859-1 จากด้านบนA0ไบต์ที่ถือว่าว่างสามารถปรากฏภายในอักขระหลายไบต์เช่น UTF-8 ที่เข้ารหัส "à" ( C3 A0) "à"ที่จะจัดการกับตัวอักษรเหล่านั้นได้อย่างปลอดภัยคุณจะต้องพูดกับพวกเขา ลักษณะการทำงานนี้ขึ้นอยู่กับการกำหนดค่าโลแคลในสภาพแวดล้อมที่ใช้งานสคริปต์ไม่ใช่สิ่งที่คุณเขียน

ฉันคิดว่าพฤติกรรมนี้เสียไปหลายวิธี แต่เราต้องเล่นด้วยมือที่เราจัดการ หากคุณกำลังทำงานกับชุดอักขระหลายไบต์ที่ไม่ซิงโครไนซ์ด้วยตนเองสิ่งที่ปลอดภัยที่สุดคือการพูดทุกอย่าง หากคุณอยู่ใน UTF-8 หรือ C คุณจะปลอดภัย (ในขณะนี้)


ช่องว่างอื่น ๆ ในสถานที่ของคุณจะต้องหลบหนีเช่นกัน ( ยกเว้นปัจจุบันหลายไบต์เนื่องจากข้อผิดพลาด )
Stéphane Chazelas

คุณจะต้องหลบหนี!เมื่อเปิดใช้งานการขยายประวัติ csh โดยปกติแล้วจะไม่ได้อยู่ในสคริปต์ [ ! -f a ]หรือfind . ! -name...ไม่เป็นไร สิ่งนี้กล่าวถึงในส่วน จำกัด ที่เข้มงวดยิ่งขึ้นของคุณแต่อาจคุ้มค่าที่จะกล่าวถึงอย่างชัดเจน
Stéphane Chazelas

ทราบว่ามีบริบทที่ตัวละครอื่น ๆ ที่จำเป็นต้องอ้างที่ชอบ: hash[foo"]"]=, ${var-foo"}"}, [[ "!" = b ]], [[ a = "]]" ]]ผู้ประกอบการ regexp [[ x =~ ".+[" ]]สำหรับ คำหลักอื่น ๆ กว่า{( if, while, for... ) จะต้องมีการยกมาเพื่อให้พวกเขาไม่ได้รับการยอมรับว่าเป็นเช่นนั้น ...
Stéphane Chazelas

ในกรณีที่เป็นอาร์กิวเมนต์บรรทัดคำสั่งการตีความขึ้นอยู่กับคำสั่งที่เป็นปัญหา (เช่น]) ดังนั้นฉันจึงไม่แสดงรายการเหล่านั้น ฉันไม่คิดว่าคำหลักใด ๆ ที่จำเป็นต้องมีการอ้างถึงในตำแหน่งอาร์กิวเมนต์
Michael Homer

2
การอ้างอิงบิวด์อินเครื่องหมายขีดคั่นหรือ% ไม่ทำอะไรเลย
Michael Homer

3

ใน GNU Parallel การทดสอบและใช้อย่างกว้างขวาง:

$a =~ s/[\002-\011\013-\032\\\#\?\`\(\)\{\}\[\]\^\*\<\=\>\~\|\; \"\!\$\&\'\202-\377]/\\$&/go;
# quote newline as '\n'                                                                                                         
$a =~ s/[\n]/'\n'/go;

จะมีการทดสอบในbash, dash, ash, ksh, และzsh fishอักขระบางตัวไม่จำเป็นต้องมีการอ้างถึงในบางเชลล์ (เวอร์ชั่น) แต่การทำงานด้านบนในเชลล์ที่ทดสอบทั้งหมด

หากคุณต้องการสตริงที่ยกมาคุณสามารถไปที่parallel --shellquote:

printf "&*\t*!" | parallel --shellquote

ฉันไม่เคยได้ยินเรื่องขนานกันมาก่อนเลย ...
Tom H

@ TomH มันจะได้รับการชื่นชมถ้าคุณสามารถใช้เวลา 5 นาทีคิดว่าเราจะไปถึงคุณได้อย่างไร
Ole Tange

ฉันคิดว่ามันเป็นปัญหาความก้าวหน้า คนส่วนใหญ่ไม่ต้องการหรือเข้าใจขนานจนกว่าพวกเขาจะผ่านขั้นตอนที่ซับซ้อนบางอย่าง เมื่อถึงเวลาที่พวกเขาเจอ xargs, nohup และอะไรทำนองนั้น นอกจากนี้ผมไม่เห็นคนจำนวนมากใช้ควบคู่ไปกับการแก้ปัญหาในการแลกเปลี่ยนสแต็คหรือเมื่อฉัน google สำหรับการแก้ปัญหาทุบตี
ทอม H

1

สำหรับโซลูชันการหลบหนีที่มีน้ำหนักเบาใน Perl ฉันกำลังทำตามหลักการของการเสนอราคาเดียว สตริง Bash ในเครื่องหมายคำพูดเดี่ยวสามารถมีอักขระใด ๆ ยกเว้นเครื่องหมายคำพูดเดียว

รหัสของฉัน:

my $bash_reserved_characters_re = qr([ !"#$&'()*;<>?\[\\`{|~\t\n]);

while(<>) {
    if (/$bash_reserved_characters_re/) {
        my $quoted = s/'/'"'"'/gr;
        print "'$quoted'";
    } else {
        print $_;
    }
}

ตัวอย่างการเรียกใช้ 1:

$ echo -n "abc" | perl escape_bash_special_chars.pl
abc

ตัวอย่างการรัน 2:

echo "abc" | perl escape_bash_special_chars.pl
'abc
'

ตัวอย่างการรัน 3:

echo -n 'ab^c' | perl escape_bash_special_chars.pl
ab^c

ตัวอย่างการเรียกใช้ 4:

echo -n 'ab~c' | perl escape_bash_special_chars.pl
'ab~c'

ตัวอย่างรัน 5:

echo -n "ab'c" | perl escape_bash_special_chars.pl
'ab'"'"'c'

echo 'ab'"'"'c'
ab'c

ใช่แล้วจุดที่ถูกต้องนั้น มุมมองของฉันคือคนส่วนใหญ่จะลงจอดบนหน้านี้เพราะพวกเขามีปัญหาในการแก้ไข ไม่ใช่เพราะสิ่งนี้ทำให้การถกเถียงทางวิชาการที่น่าสนใจ นั่นเป็นเหตุผลที่ฉันต้องการนำเสนอโซลูชั่นและหารือเกี่ยวกับข้อดีของพวกเขาแม้ในขณะที่อยู่นอกหัวข้อเล็กน้อย
Jari Turkia

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