มีความแตกต่างระหว่างสองสิ่งนี้หรือไม่
[[ $a == z* ]]
และ
[ $a == z* ]
ฉันสามารถมีตัวอย่างที่พวกเขาจะมีผลลัพธ์ที่แตกต่างกันหรือไม่
นอกจากนี้การทำงานของ[[ ]]แตกต่างกัน[ ]อย่างไร
มีความแตกต่างระหว่างสองสิ่งนี้หรือไม่
[[ $a == z* ]]
และ
[ $a == z* ]
ฉันสามารถมีตัวอย่างที่พวกเขาจะมีผลลัพธ์ที่แตกต่างกันหรือไม่
นอกจากนี้การทำงานของ[[ ]]แตกต่างกัน[ ]อย่างไร
คำตอบ:
ความแตกต่างระหว่าง[[ … ]]และ[ … ]ถูกปกคลุมส่วนใหญ่ในการใช้วงเล็บเดี่ยวหรือเตียงคู่ - ทุบตี Crucially [[ … ]]เป็นไวยากรณ์พิเศษในขณะที่[เป็นชื่อที่ดูตลกสำหรับคำสั่ง [[ … ]]มีกฎไวยากรณ์พิเศษสำหรับสิ่งที่อยู่ภายใน[ … ]ไม่ได้
ด้วยรอยย่นเพิ่มเติมของ wildcard นี่คือวิธีการ[[ $a == z* ]]ประเมิน:
[[ … ]]$a == z*==ผู้ประกอบการไบนารีกับตัวถูกดำเนินและ$az*aขยายตัวถูกดำเนินการครั้งแรกในค่าของตัวแปร==ผู้ปฏิบัติงาน: ทดสอบว่าค่าของตัวแปรaตรงกับรูปแบบz*หรือไม่นี่คือวิธีการ[ $a == z* ]ประเมิน:
[คำสั่งที่มีการขัดแย้งที่เกิดขึ้นจากการประเมินคำ$a, ==, ,z*]$aaaเป็นสตริง 6 ตัวfoo b*(ที่ได้รับโดยเช่นa='foo b*') และรายชื่อของไฟล์ในไดเรกทอรีปัจจุบันเป็น (คนbar, baz, qux, zim, zum) แล้วผลของการขยายตัวที่เป็นรายการต่อไปนี้คำ: [, foo, bar, baz, ==, zim, ,zum][ด้วยพารามิเตอร์ที่ได้รับในขั้นตอนก่อนหน้า
[คำสั่งบ่นถึงข้อผิดพลาดทางไวยากรณ์และส่งคืนสถานะ 2หมายเหตุ: ใน[[ $a == z* ]]ขั้นตอนที่ 3 ค่าของaจะไม่ได้รับการแยกคำและการสร้างชื่อไฟล์เนื่องจากอยู่ในบริบทที่คาดว่าจะมีคำเดียว (อาร์กิวเมนต์ซ้ายมือของโอเปอเรเตอร์ที่มีเงื่อนไข==) ในกรณีส่วนใหญ่หากคำเดียวทำให้รู้สึกถึงตำแหน่งนั้นการขยายตัวของตัวแปรจะทำงานเหมือนคำพูดในเครื่องหมายคำพูดคู่ อย่างไรก็ตามมีข้อยกเว้นสำหรับกฎนั้น: ใน[[ abc == $a ]]หากค่าของaประกอบด้วยอักขระตัวแทนนั้นaจะถูกจับคู่กับรูปแบบสัญลักษณ์แทน ตัวอย่างเช่นหากค่าของaเป็นa*แล้ว[[ abc == $a ]]จะเป็นจริง (เพราะอักขระตัวแทน*มาจากการขยายตัวของการ$aจับคู่ที่ไม่มีเงื่อนไข*) ในขณะที่[[ abc == "$a" ]]เป็นเท็จ (เพราะตัวอักษรธรรมดา*มาจากการขยายที่ยกมาของ$aไม่ตรงกับbc) ภายใน[[ … ]], ราคาคู่ไม่ได้สร้างความแตกต่างยกเว้นทางด้านขวามือของผู้ประกอบการจับคู่สาย ( =, ==, !=และ=~)
[เป็นนามแฝงสำหรับtestคำสั่ง Unix เวอร์ชัน 6 มีifคำสั่ง แต่เวอร์ชัน 7 (1979) มาพร้อมกับBourne shellใหม่ที่มีโครงสร้างการเขียนโปรแกรมไม่กี่รายการรวมถึงโครงสร้าง if-then-else-elif-fi และ Unix เวอร์ชัน 7 ได้เพิ่มtestคำสั่งที่ดำเนินการเกือบทั้งหมด "การทดสอบ" ที่ดำเนินการโดยifคำสั่งในเวอร์ชันที่เก่ากว่า
[ถูกสร้างขึ้นมาเพื่อนามแฝงtestและทั้งสองได้ทำที่สร้างขึ้นในเปลือกในระบบยูนิกซ์ที่สาม (1981) แม้ว่ามันควรจะสังเกตว่าตัวแปร Unix บางตัวไม่ได้มี[คำสั่งจนกระทั่งมากหลังจากนั้น ( จนถึงต้นยุค 2000 ในshBSD บางอันซึ่งมีพื้นฐานมาจากเชลล์ Almquist ( บิวอินtestได้รวมอยู่ในashแหล่งของมันเสมอ) BSD มันถูกปิดใช้งานในขั้นต้น))
โปรดทราบว่าtestaka [เป็นคำสั่งที่จะทำ "ทดสอบ" =ที่มีการกำหนดว่าคำสั่งที่ไม่เป็นจึงมีเหตุผลที่จะกระจ่างระหว่างผู้ประกอบการที่ได้รับมอบหมายและความเท่าเทียมกันไม่ให้ผู้ประกอบการเท่าเทียมกันคือ ==ได้รับการสนับสนุนโดยการนำไปใช้งานล่าสุดของ[(และเป็นเพียงนามแฝง=)
เนื่องจาก[ไม่มีอะไรมากกว่าคำสั่งจึงแยกวิเคราะห์แบบเดียวกับคำสั่งอื่น ๆ โดยเชลล์
โดยเฉพาะอย่างยิ่งในตัวอย่างของคุณ$aเนื่องจากไม่มีการอ้างอิงจะถูกแบ่งออกเป็นหลายคำตามกฎปกติของการแยกคำและแต่ละคำจะได้รับการสร้างชื่อไฟล์หรือที่รู้จักกันในชื่อ globbing เพื่อให้ได้คำที่มากขึ้น อาร์กิวเมนต์แยกจาก[คำสั่ง
ในทำนองเดียวกันจะขยายไปยังรายการของชื่อไฟล์ในไดเรกทอรีปัจจุบันที่เริ่มต้นด้วยz*z
ดังนั้นสำหรับตัวอย่างเช่นถ้า$aเป็นb* = xและมีz1, z2, b1และb2ไฟล์ในไดเรกทอรีปัจจุบันที่[คำสั่งจะได้รับ 9 ข้อโต้แย้ง: [, b1, b2, =, x, ==, z1, และz2]
[แยกวิเคราะห์ข้อโต้แย้งของมันในฐานะการแสดงออกตามเงื่อนไข อาร์กิวเมนต์ 9 ข้อนั้นไม่ได้รวมอยู่ในนิพจน์เงื่อนไขที่ถูกต้องดังนั้นจึงอาจส่งคืนข้อผิดพลาดได้
การ[[ ... ]]สร้างได้รับการแนะนำโดย Korn shell อาจประมาณปี 1988 ksh86aในปี 1987 ไม่ได้มีมันในขณะที่ksh88มีมันตั้งแต่เริ่มต้น
ข้าง ksh (การใช้งานทั้งหมด) [[...]]ได้รับการสนับสนุนโดย bash (ตั้งแต่รุ่น 2.02) และ zsh แต่การใช้งานทั้งสามนั้นแตกต่างกันและมีความแตกต่างระหว่างแต่ละเวอร์ชันของเชลล์เดียวกันแม้ว่าการเปลี่ยนแปลงจะเข้ากันได้โดยทั่วไป=~โอเปอเรเตอร์ที่รู้จักกันว่าจะทำลายสคริปต์บางตัวหลังจากเวอร์ชั่นที่แน่นอนเมื่อพฤติกรรมของมันเปลี่ยนไป) [[...]]ไม่ได้ระบุโดย POSIX หรือ Unix หรือ Linux (LSB) มันได้รับการพิจารณาเพื่อรวมสองสามครั้ง แต่ไม่รวมเป็นหน้าที่การใช้งานทั่วไปของมันที่ได้รับการสนับสนุนโดยเปลือกหอยใหญ่นั้นครอบคลุมโดย[คำสั่งและการcase-in-esacสร้าง
โครงสร้างทั้งหมด[[ ... ]]ประกอบเป็นคำสั่ง นั่นคือมันมีสถานะการออก (ซึ่งเป็นสินทรัพย์ที่สำคัญที่สุดเนื่องจากเป็นผลของการประเมินการแสดงออกตามเงื่อนไข) คุณสามารถไพพ์ไปยังคำสั่งอื่น (แม้ว่ามันจะไม่เป็นประโยชน์) และโดยทั่วไปจะใช้มันทุกที่ที่คุณต้องการ ใช้คำสั่งอื่น ๆ (ภายในเชลล์เท่านั้นเนื่องจากเป็นโครงสร้างเชลล์) แต่ไม่ได้แยกวิเคราะห์เหมือนกับคำสั่งทั่วไปธรรมดา ภายในมีการแยกวิเคราะห์โดยเชลล์เป็นนิพจน์เงื่อนไขและกฎปกติของการแบ่งคำและการสร้างชื่อไฟล์จะใช้แตกต่างกัน
[[ ... ]]ไม่เกี่ยวกับความรู้==จากการเริ่มต้นและเทียบเท่ากับ1= ความผิดพลาดของ ksh คือ (และก่อให้เกิดความสับสนและข้อบกพร่องมากมาย) นั่นคือ=และ==ไม่ใช่ตัวดำเนินการความเสมอภาค แต่เป็นตัวดำเนินการจับคู่รูปแบบ (แม้ว่ารูปแบบการจับคู่สามารถปิดการใช้งานได้
ในรหัสของคุณด้านบน[[ $a == z* ]]เชลล์จะแยกวิเคราะห์ว่าเป็นโทเค็นหลาย ๆ ตัวในกฎที่คล้ายกับกฎทั่วไปยอมรับว่าเป็นการเปรียบเทียบการจับคู่รูปแบบถือว่าz*เป็นรูปแบบที่จะจับคู่กับเนื้อหาของaตัวแปร
โดยทั่วไปแล้วการถ่ายตัวเองด้วยเท้า[[ ... ]]ก็ยากกว่าการใช้[คำสั่ง แต่กฎบางอย่างเช่น
-aหรือ-o(ใช้[คำสั่งหลายคำสั่งและตัวดำเนินการ&&และ|| เชลล์ )สร้าง[ความน่าเชื่อถือด้วย POSIX shells
[[...]]ในเชลล์ที่แตกต่างกันรองรับโอเปอเรเตอร์พิเศษเช่น-nt, regexp จับคู่โอเปอเรเตอร์ ... แต่รายการและลักษณะการทำงานนั้นแตกต่างกันไปจากเชลล์หนึ่งไปยังเชลล์และรุ่นต่อรุ่น
ดังนั้นถ้าคุณไม่ทราบว่าเชลล์และเวอร์ชันต่ำสุดของสคริปต์ของคุณจะถูกตีความด้วยวิธีใดมันอาจจะปลอดภัยกว่าหากใช้[คำสั่งมาตรฐาน
1ข้อยกเว้น: [[...]]เพิ่มลงใน bash ในเวอร์ชัน2.02แล้ว จนกว่า2.03จะมีการเปลี่ยนแปลง[[ x = '?' ]]จะกลับเป็นจริงในขณะที่[[ x == '?' ]]จะกลับเท็จ ที่มีการอ้างไม่ได้ป้องกันการจับคู่รูปแบบเมื่อใช้=ประกอบในรุ่นนั้น ==แต่เมื่อใช้
[ '!' = foo -o a = a ]ในbashตัวอย่างเช่น
ทั้งสองถูกใช้เพื่อประเมินนิพจน์และ [[จะไม่ทำงานกับ POSIX bourn เชลล์ที่เก่ากว่าและ [[ยังรองรับการจับคู่รูปแบบและ regex ตัวอย่างลองสิ่งเหล่านี้
[ $n -eq 0 -a $y -eq 0 ] && echo "Error" || echo "Ok"
[[ $n -eq 0 && $y -eq 0 ]] && echo "Error" || echo "Ok"
[[...]]รองรับ regexps เฉพาะในบางรุ่นของเชลล์บางรุ่นเช่นเดียวกับบางรุ่นที่[รองรับการจับคู่ regexp สำหรับการเปรียบเทียบทางคณิตศาสตร์ในเปลือกหอยที่สนับสนุน[[คุณควรเขียน(( n == 0 && y == 0))