ใน Bash เมื่อระบุอาร์กิวเมนต์บรรทัดคำสั่งให้กับคำสั่งจำเป็นต้องใช้อักขระใดในการหลีกเลี่ยง
พวกเขาจะถูก จำกัด ให้ metacharacters ของทุบตี: พื้นที่แท็บ
 |, &, ;, (, ), <และ>?
ใน Bash เมื่อระบุอาร์กิวเมนต์บรรทัดคำสั่งให้กับคำสั่งจำเป็นต้องใช้อักขระใดในการหลีกเลี่ยง
พวกเขาจะถูก จำกัด ให้ metacharacters ของทุบตี: พื้นที่แท็บ
 |, &, ;, (, ), <และ>?
คำตอบ:
อักขระต่อไปนี้มีความหมายพิเศษต่อเชลล์เองในบางบริบทและอาจจำเป็นต้องมีการหลบหนีในอาร์กิวเมนต์:
` Backtick (U + 0060 Grave Accent)~ หนอน (U + 007E)! เครื่องหมายอัศเจรีย์ (U + 0021)# Hash (เครื่องหมายหมายเลข U + 0023)$ เครื่องหมายดอลลาร์ (U + 0024)& เครื่องหมาย & (U + 0026)* เครื่องหมายดอกจัน (U + 002A)( วงเล็บซ้าย (U + 0028)) วงเล็บปิด (U + 0029)⇥) แท็บ (U + 0009){ วงเล็บปีกกาซ้าย (U + 007B วงเล็บปีกกาซ้าย)[ วงเล็บเหลี่ยมด้านซ้าย (U + 005B)| แถบแนวตั้ง (U + 007C เส้นแนวตั้ง)\ ทับขวา (U + 005C ย้อนโซลิดัส); อัฒภาค (U + 003B)' คำพูดเดี่ยว / Apostrophe (U + 0027)" เครื่องหมายคำพูดคู่ (U + 0022)↩ บรรทัดใหม่ (U + 000A)< น้อยกว่า (U + 003C)> มากกว่า (U + 003E)? เครื่องหมายคำถาม (U + 003F)ตัวละครเหล่านี้บางตัวใช้สำหรับสิ่งต่าง ๆ และในที่มากกว่าตัวละครที่ฉันเชื่อมโยง
มีบางกรณีที่มีมุมที่เป็นทางเลือกอย่างชัดเจน:
!สามารถปิดการใช้งานด้วย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 คุณจะปลอดภัย (ในขณะนี้)
!เมื่อเปิดใช้งานการขยายประวัติ csh โดยปกติแล้วจะไม่ได้อยู่ในสคริปต์ [ ! -f a ]หรือfind . ! -name...ไม่เป็นไร สิ่งนี้กล่าวถึงในส่วน จำกัด ที่เข้มงวดยิ่งขึ้นของคุณแต่อาจคุ้มค่าที่จะกล่าวถึงอย่างชัดเจน
                    hash[foo"]"]=, ${var-foo"}"}, [[ "!" = b ]], [[ a = "]]" ]]ผู้ประกอบการ regexp [[ x =~ ".+[" ]]สำหรับ คำหลักอื่น ๆ กว่า{( if, while, for... ) จะต้องมีการยกมาเพื่อให้พวกเขาไม่ได้รับการยอมรับว่าเป็นเช่นนั้น ...
                    ]) ดังนั้นฉันจึงไม่แสดงรายการเหล่านั้น ฉันไม่คิดว่าคำหลักใด ๆ ที่จำเป็นต้องมีการอ้างถึงในตำแหน่งอาร์กิวเมนต์
                    ใน 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สำหรับโซลูชันการหลบหนีที่มีน้ำหนักเบาใน 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