มีความแตกต่างระหว่างสองสิ่งนี้หรือไม่
[[ $a == z* ]]
และ
[ $a == z* ]
ฉันสามารถมีตัวอย่างที่พวกเขาจะมีผลลัพธ์ที่แตกต่างกันหรือไม่
นอกจากนี้การทำงานของ[[ ]]
แตกต่างกัน[ ]
อย่างไร
มีความแตกต่างระหว่างสองสิ่งนี้หรือไม่
[[ $a == z* ]]
และ
[ $a == z* ]
ฉันสามารถมีตัวอย่างที่พวกเขาจะมีผลลัพธ์ที่แตกต่างกันหรือไม่
นอกจากนี้การทำงานของ[[ ]]
แตกต่างกัน[ ]
อย่างไร
คำตอบ:
ความแตกต่างระหว่าง[[ … ]]
และ[ … ]
ถูกปกคลุมส่วนใหญ่ในการใช้วงเล็บเดี่ยวหรือเตียงคู่ - ทุบตี Crucially [[ … ]]
เป็นไวยากรณ์พิเศษในขณะที่[
เป็นชื่อที่ดูตลกสำหรับคำสั่ง [[ … ]]
มีกฎไวยากรณ์พิเศษสำหรับสิ่งที่อยู่ภายใน[ … ]
ไม่ได้
ด้วยรอยย่นเพิ่มเติมของ wildcard นี่คือวิธีการ[[ $a == z* ]]
ประเมิน:
[[ … ]]
$a == z*
==
ผู้ประกอบการไบนารีกับตัวถูกดำเนินและ$a
z*
a
ขยายตัวถูกดำเนินการครั้งแรกในค่าของตัวแปร==
ผู้ปฏิบัติงาน: ทดสอบว่าค่าของตัวแปรa
ตรงกับรูปแบบz*
หรือไม่นี่คือวิธีการ[ $a == z* ]
ประเมิน:
[
คำสั่งที่มีการขัดแย้งที่เกิดขึ้นจากการประเมินคำ$a
, ==
, ,z*
]
$a
a
a
เป็นสตริง 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 ในsh
BSD บางอันซึ่งมีพื้นฐานมาจากเชลล์ Almquist ( บิวอินtest
ได้รวมอยู่ในash
แหล่งของมันเสมอ) BSD มันถูกปิดใช้งานในขั้นต้น))
โปรดทราบว่าtest
aka [
เป็นคำสั่งที่จะทำ "ทดสอบ" =
ที่มีการกำหนดว่าคำสั่งที่ไม่เป็นจึงมีเหตุผลที่จะกระจ่างระหว่างผู้ประกอบการที่ได้รับมอบหมายและความเท่าเทียมกันไม่ให้ผู้ประกอบการเท่าเทียมกันคือ ==
ได้รับการสนับสนุนโดยการนำไปใช้งานล่าสุดของ[
(และเป็นเพียงนามแฝง=
)
เนื่องจาก[
ไม่มีอะไรมากกว่าคำสั่งจึงแยกวิเคราะห์แบบเดียวกับคำสั่งอื่น ๆ โดยเชลล์
โดยเฉพาะอย่างยิ่งในตัวอย่างของคุณ$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))