ความเรียบง่ายสง่างามของ Bash ดูเหมือนว่าจะหลงทางในหน้าเพจขนาดใหญ่
นอกจากนี้ยังมีการแก้ปัญหาที่ดีข้างต้นผมคิดว่าฉันพยายามที่จะทำให้คุณมีแผ่นโกงในวิธีการที่จะแยกวิเคราะห์ทุบตีและตีความงบ จากนั้นการใช้แผนงานนี้ฉันจะแยกตัวอย่างที่ผู้ถามเสนอเพื่อช่วยให้คุณเข้าใจได้ดีขึ้นว่าทำไมพวกเขาถึงไม่ทำงานตามที่ตั้งใจไว้
หมายเหตุ: เชลล์สคริปต์ถูกใช้โดยตรง อินพุตบรรทัดที่พิมพ์เป็นส่วนขยายประวัติครั้งแรก
สายทุบตีแต่ละ tokenized แรกหรือในคำอื่น ๆ ที่สับเป็นสิ่งที่เรียกว่าราชสกุล (การโทเค็นเกิดขึ้นก่อนการขยายอื่น ๆ ทั้งหมดรวมถึงวงเล็บ, ตัวหนอน, พารามิเตอร์, คำสั่ง, เลขคณิต, กระบวนการ, การแยกคำ, และการขยายชื่อไฟล์)
โทเค็นที่นี่หมายถึงส่วนหนึ่งของบรรทัดอินพุตที่คั่น (คั่นด้วย) โดยหนึ่งในอักขระเมตาพิเศษเหล่านี้:
space, - White space...
tab,
newline,
‘<’, - Redirection & piping...
‘|’,
‘>’
‘&’, - And/Both < | > | >> .or. &<file descriptor>
‘;’, - Command termination
‘(’, - Subshell, closed by - ‘)’
Bash ใช้อักขระพิเศษอื่น ๆ อีกมากมาย แต่มีเพียง 10 ตัวเท่านั้นที่สร้างโทเค็นเริ่มต้น
อย่างไรก็ตามเนื่องจากบางครั้งต้องใช้เมตาอักขระเหล่านี้ในโทเค็นจึงจำเป็นต้องมีวิธีที่จะกำจัดความหมายพิเศษของพวกเขา สิ่งนี้เรียกว่าการหลบหนี การหลบหนีทำได้โดยการใส่สตริงของอักขระหนึ่งตัวหรือมากกว่านั้น (เช่น'xx..'
, "xx.."
) หรือโดยนำหน้าอักขระแต่ละตัวที่มีเครื่องหมายทับด้านหลัง (เช่น\x
) (มันซับซ้อนกว่านี้เล็กน้อยเนื่องจากต้องใส่เครื่องหมายอัญประกาศด้วยเช่นกันและเนื่องจากเครื่องหมายคำพูดคู่ไม่ได้พูดทุกอย่าง แต่ตอนนี้การทำให้เรียบง่ายจะเกิดขึ้นในตอนนี้)
อย่าสับสนระหว่างการอ้างอิงข้อความโดยใช้ความคิดในการอ้างอิงข้อความเช่นในภาษาอื่น ๆ สิ่งที่อยู่ระหว่างเครื่องหมายอัญประกาศใน bash ไม่ใช่สตริง แต่เป็นส่วนของบรรทัดอินพุตที่มีเมตาอักขระที่หลบหนีดังนั้นจึงไม่คั่นโทเค็น
หมายเหตุมีความแตกต่างที่สำคัญระหว่าง'
และ"
แต่นั่นก็เป็นอีกวัน
เมตาอักขระที่ไม่ใช้ค่า Escape ที่เหลือจะกลายเป็นตัวคั่นโทเค็น
ตัวอย่างเช่น,
$ echo "x"'y'\g
xyg
$ echo "<"'|'\>
<|>
$ echo x\; echo y
x; echo y
ในตัวอย่างแรกมีสองราชสกุลผลิตโดยคั่นพื้นที่: และecho
xyz
เช่นเดียวกันในตัวอย่างที่ 2
ในตัวอย่างที่สามอัฒภาครอดจึงมี 4 ราชสกุลผลิตโดยคั่นพื้นที่echo
, x;
, และecho
y
โทเค็นแรกจะถูกเรียกใช้เป็นคำสั่งและใช้โทเค็นสามตัวถัดไปเป็นอินพุต หมายเหตุที่ 2 echo
จะไม่ถูกดำเนินการ
สิ่งสำคัญที่ต้องจำไว้คือลักษณะแรกทุบตีหนีตัวอักษร ( '
, "
และ\
) แล้วมองหาที่ไม่ใช้ Escape คั่นเมตาตัวอักษรในลำดับที่
หากไม่ได้หลบหนีตัวละครพิเศษทั้ง 10 ตัวนี้จะทำหน้าที่เป็นtoken
ตัวคั่น บางคนมีความหมายเพิ่มเติม แต่ก่อนอื่นพวกเขาเป็นตัวคั่นโทเค็น
grep คาดหวังอะไร
ในตัวอย่างข้างต้น grep grep
ต้องการราชสกุลเหล่านี้string
, filename
,
คำถามแรกของคำถามคือ:
$ grep (จากนั้น | นั่น) xx
ในกรณีนี้(
, )
และ|
ตัวละครที่ไม่ใช้ Escape เมตาและเพื่อทำหน้าที่ในการแยกการป้อนข้อมูลลงในราชสกุลเหล่านี้: grep
, (
, then
, |
, there
, และ)
x.x
grep ต้องการที่จะเห็นgrep
, และthen|there
x.x
คำถามที่สองคือ:
grep "(จากนั้น | ตรงนั้น)" xx
นี้ tokenizes เข้าgrep
, ,(then|there)
x.x
คุณสามารถเห็นสิ่งนี้หากคุณสลับ grep สำหรับ echo:
echo "(จากนั้น | นั่น)" xx
(จากนั้น | นั่น) xx