ตัวอย่างเช่นคำสั่งต่อไปนี้ใช้ไม่ได้:
if [[-e xyz]]; then echo File exists;fi
ksh ให้ข้อผิดพลาดดังต่อไปนี้
[[-e: command not found
นั่นเป็นเพราะ "[[-" นั้นคลุมเครือหรือไม่
ตัวอย่างเช่นคำสั่งต่อไปนี้ใช้ไม่ได้:
if [[-e xyz]]; then echo File exists;fi
ksh ให้ข้อผิดพลาดดังต่อไปนี้
[[-e: command not found
นั่นเป็นเพราะ "[[-" นั้นคลุมเครือหรือไม่
คำตอบ:
คำอธิบายที่ง่ายที่สุดจะเป็นเพราะในคู่มือก็จะปรากฏเป็น[[ expression ]]ดังนั้นจะต้องมีช่องว่างระหว่าง[[และและปิดexpression ]]แต่แน่นอนว่าเราสามารถพยายามมองลึกลงไปอีก เชลล์มีไวยากรณ์ที่ค่อนข้างซับซ้อนและพึ่งพาแนวคิดของ "การแยกคำ" อย่างหนัก โดยเฉพาะอย่างยิ่ง ksh (1)สถานะด้วยตนเอง:
เชลล์เริ่มต้นแยกวิเคราะห์อินพุตโดยแบ่งเป็นคำ คำซึ่งเป็นลำดับของอักขระถูกคั่นด้วยอักขระช่องว่างสีขาว (ช่องว่างแท็บและขึ้นบรรทัดใหม่) หรืออักขระเมตา (<,>, |,;, และ (และ)) นอกเหนือจากการลบคำเว้นวรรคและแท็บจะถูกละเว้นในขณะที่บรรทัดใหม่มักจะกำหนดคำสั่ง
ดังนั้นตามที่ระบุไว้ในคู่มือลำดับของตัวละคร[[-eถือว่าเป็นคำของเชลล์ kshจะค้นหาคำสั่งดังกล่าวในรายการบิวด์อินและโอเปอเรเตอร์พิเศษ (เช่นforหรือwhile) จากนั้นค้นหาคำสั่งภายนอก - และvoilà - ไม่พบดังนั้นจึงมีข้อความแสดงข้อผิดพลาดเกี่ยวกับคำสั่งที่ไม่พบ
ในกรณี[[นี้ไม่ใช่อักขระพิเศษเมตาเช่นกัน หากพวกเขาเป็น-eส่วนหนึ่งใน[[-eจะถือว่าเป็นคำเปลือกไม่ใช่ข้อโต้แย้งกับ[[ตัวเอง อย่างไรก็ตาม[[คำอธิบายเป็นคำสั่งผสมและคู่มือบอกสิ่งต่อไปนี้:
คำสั่งผสมถูกสร้างขึ้นโดยใช้คำสงวนต่อไปนี้ - คำเหล่านี้จะได้รับการยอมรับเฉพาะในกรณีที่พวกเขาไม่ได้ยกมาและหากพวกเขาจะใช้เป็นคำแรกของคำสั่ง (เช่นพวกเขาไม่สามารถนำหน้าด้วยการกำหนดพารามิเตอร์หรือเปลี่ยนเส้นทาง)
ดังนั้นเพื่อที่[[จะได้รับการยอมรับในฐานะคำสั่งผสมมันจะต้องเป็นคำแรกของคำสั่งหรือรายการคำสั่งซึ่งโดยคำจำกัดความก่อนหน้าของคำว่า "คำว่า" หมายความว่ามันจะต้องถูกคั่นด้วยช่องว่างแท็บหรือบรรทัดใหม่จากอื่น ๆ คำ / ข้อโต้แย้ง
คุณได้ถามในความคิดเห็น : "ทำไม parser ไม่สามารถหยุดทันทีที่พบ" [["รูปแบบและถือว่าเป็นจุดเริ่มต้นของคำสั่งตามเงื่อนไข?" คำตอบสั้น ๆ อาจเป็นเพราะ 1) อิทธิพลของ[วากยสัมพันธ์เนื่องจากเดิมเป็นคำสั่งภายนอกและสำหรับการปฏิบัติตามมาตรฐาน POSIX นั้นมีอยู่ว่าเป็นคำสั่งภายนอกแม้กระทั่งทุกวันนี้และ 2) เพราะตัวแยกวิเคราะห์เชลล์ถูกสร้างขึ้นมา ตัวแยกวิเคราะห์เชลล์สามารถจดจำอักขระพิเศษอื่น ๆ ที่ไม่คั่นด้วยช่องว่าง: echo $((2+2))และ(echo foobar)ทำงานได้อย่างสมบูรณ์แบบ บางทีในอนาคตเมื่อkshการพัฒนาดำเนินการต่อหรือมีปรากฏเป็นส้อมหรือโคลน (ชอบmkshหรือpdksh) [[-eคนที่จะใช้ไวยากรณ์พื้นที่น้อยในการ
[[เรียกว่า "คำสงวน" (ดูหัวข้อ 2.9 ของภาษาคำสั่งเชลล์ ) ตามคำนิยาม POSIX คำที่สงวนไว้จะต้องคั่นด้วยช่องว่าง ในทางตรงกันข้าม(ผู้ดำเนินการและรัฐมาตรฐานในส่วนที่ 2.9 "การเป็นตัวแทนรวมถึงการเว้นวรรคระหว่างโทเค็นในบางสถานที่ที่<blank>ไม่จำเป็นต้องใช้ s (เมื่อโทเค็นตัวใดตัวหนึ่งเป็นตัวดำเนินการ)" ดูการสนทนาที่เกี่ยวข้อง: POSIX ไวยากรณ์ไวยากรณ์: ทำไม Brace Group ต้องการพื้นที่แรก แต่ไม่ได้ Subshellcharคำหลัก แต่คุณยังคงไม่สามารถเขียนcharsomeletter = 'A';และคาดว่า parser charที่จะหยุดหลังจากที่ได้เห็น
i--<=++j i -- <= ++ j
_) ksh มี(ในฐานะที่เป็นผู้ประกอบการและจะแยกวิเคราะห์เป็น(echo hello) ( echo hello )มันมีif, {, [[และอื่น ๆ ที่คำหลักและifx, {xและ[[xแต่ละคนโทเค็น - เช่นวิธีการcharsomeletterเป็นหนึ่งในโทเค็นซี ในทางตรงกันข้ามการ unquoted (xใน ksh สองราชสกุล - เช่นวิธีการi--สองราชสกุลใน C. สิ่งที่มันแนวคิดแม้หมายความว่าจะเป็นผู้ประกอบการที่แตกต่างระหว่างเปลือกหอยบอร์นสไตล์ (เช่น ksh) และ C แต่ Peter A. ไนเดอร์ชี้ให้เห็นความคล้ายคลึงกันของคำศัพท์จริง
เป็นสิ่งสำคัญที่ควรทราบก็คือว่า[เป็นคำสั่งและคำหลักเปลือก[[ในทุบตีและ ksh [จะขึ้นอยู่กับ
[[[ถูกนำมาใช้ในทางที่คล้ายกับ บางครั้งคุณยังสามารถแทนที่[ ]ด้วย[[ ]]กับการเปลี่ยนแปลงในพฤติกรรมไม่ ด้วย[เช่นเดียวกับคำสั่งใด ๆ พื้นที่มีผลบังคับใช้ระหว่างคำสั่งและข้อโต้แย้ง [[เช่นเดียวกับ
/usr/bin/[เราใช้จะมีเพียง ตอนนี้เชลล์ส่วนใหญ่[สร้างขึ้นเพื่อประสิทธิภาพ - แต่ไวยากรณ์เหมือนกัน ในเปลือกหอยที่ให้[[มันทำหน้าที่เป็นมากขึ้นหลากหลาย[ทางเลือก
นี่คือคำอธิบายสำหรับ[ในทุบตี:
$ help [
[: [ arg... ]
Evaluate conditional expression.
This is a synonym for the "test" builtin, but the last argument must
be a literal `]', to match the opening `['.
ดังนั้น[จะเทียบเท่ากับtest(นอกเหนือจากการคาดหวัง]ข้อโต้แย้งในตอนท้าย) help testจะให้รายละเอียดเพิ่มเติมกับมัน help [[คุณสามารถเปรียบเทียบนี้
นอกจากนี้ยังมี man page สำหรับคำสั่งภายนอก[( man \[)
ในกรณีของ
if [[-e
[มิได้[[มีคำสั่ง คำเต็ม[[-eคือif [[-eทำให้การทดสอบสำหรับ / เท็จจริง ดังนั้นคำสั่งจะ[[-eมีอยู่? นั่นเป็นเพราะ "[[-" นั้นคลุมเครือหรือไม่
ใช่. หรือไม่. [[-eมันคืออะไร: ไม่มีสิ่งใดที่เชลล์เข้าใจดังนั้นจึงถือว่ามันเป็นคำสั่งของมันเอง ;-)
[[-eเป็นชื่อคำสั่งที่อาจใช้งานได้ (ถ้าดูแปลก)
พื้นที่เป็นตัวแยกและเป็นสิ่งจำเป็น ตามที่คุณเห็นจากshellcheck:
$ shellcheck gmail-browse-msgs-algorithm.sh
In gmail-browse-msgs-algorithm.sh line 847:
[[$Today != "${DaysArr[ i + DAY_DELETED_ON_NDX ]}" ]] && continue
^-- SC1035: You need a space after the [[ and before the ]].
(รองรับทั้ง ksh และ bash [[และไม่ทำงานหากไม่มีที่ว่าง Shellcheck ให้ผลลัพธ์ที่เหมือนกันกับสคริปต์ ksh และ bash ที่คล้ายกันที่มีบรรทัด buggy นั้น)
ทำไม deliminators มีความจำเป็นที่จะทำอย่างไรกับราชสกุลและคำศัพท์
kshเชลล์ในคำถาม Bash ยืม[[ตัวดำเนินการจากkshและในคำถามนี้พฤติกรรมของพวกเขาเหมือนกัน แต่ฉันจะระมัดระวังข้อสันนิษฐานเนื่องจากมีความแตกต่างที่สำคัญระหว่างkshและbashพฤติกรรมและ internals นั่นเป็นเพราะ shellcheck ทำงานกับ bash script อาจไม่จำเป็นต้องเป็นเครื่องมือที่เหมาะสมสำหรับสคริปต์ ksh สิ่งที่ต้องจำไว้ในขณะที่ใกล้เปลือกหอยที่แตกต่างกัน
[[กฎในตัว ฉันไม่ได้คาดเดาว่าkshจะเป็นเชลล์ที่shellcheckสามารถหาข้อผิดพลาดได้ฉันหวังว่าคนอื่นจะชื่นชมkshและbashเป็นล่ามที่ต่างกันสองคน ขอบคุณที่พูดถึงมัน สิ่งที่ควรค่ายิ่งกว่า[[คือการทุบตีในขณะที่[เป็นคำสั่งภายนอก
[เป็น bash ในตัวด้วย :) manpages.ubuntu.com/manpages/bionic/man7/bash-builtins.7.htmlแต่คุณไม่ได้อยู่ไกล[หรือtestต้องเป็นคำสั่งภายนอก ในสมัยของบอร์นเชลล์[ในความเป็นจริงคำสั่งภายนอกและยังคงมีอยู่ทุกวันนี้/usr/bin/[เนื่องจาก POSIX ต้องการให้มันเป็นคำสั่งภายนอกpubs.opengroup.org/onlinepubs/009695399/utilities/test.html มีน้อยมากที่ POSIX ต้องการ ถูกสร้างขึ้นในpubs.opengroup.org/onlinepubs/009695399/idx/sbi.html Builtin [สำหรับประสิทธิภาพ
ksh; ใช้ hashbang -s kshหรือ Btw, ksh และทุบตีได้[["สร้างขึ้นใน" แต่มันเป็นคำหลักที่แตกต่าง[ซึ่งเป็นbuiltin เปลือก (ksh:; whence -v [ [[bash type [ [[:) Builtins และคำสั่งภายนอกมีความเหมือนกันทางวากยสัมพันธ์ วิธีหนึ่งที่[[แตกต่างจาก[นั้นคือ[[ระงับการขยายตัวบางอย่างในการโต้แย้งของมันซึ่งมันไม่สามารถเป็นแบบบิลท์อินได้มากเท่าที่{ไม่สามารถจัดกลุ่มได้ นี่อาจจะเป็นเหตุผลที่{x(หรือ[[x) เป็นหนึ่งที่รู้สึกแปลกโทเค็น ฉันคิดว่ามันเป็นสิทธิที่จะพูด builtins และคำหลักlexicallyแต่ไม่ไวยากรณ์ที่คล้ายกัน @SergiyKolodyazhnyy
[[สามารถเป็นคำสั่งภายนอก! นั่นอาจเป็นโปรแกรมและไม่ใช่ไวยากรณ์ที่เชลล์ของคุณสนับสนุนโดยตรง การสนับสนุนไวยากรณ์ที่ไม่ต้องเว้นวรรคจะเป็นไปได้kshแต่จะล้มเหลวในระบบภายนอก[[ดังนั้นด้วยเหตุผลด้านความเข้ากันได้ดีกว่าเพื่อรักษาพื้นที่ที่ต้องการ
เนื่องจาก[[-eสามารถมีส่วนร่วมในการขยายเชลล์ (มันสามารถใช้เช่น
echo [[-e]*
เพื่อแสดงรายการไฟล์ทั้งหมดที่เริ่มต้นด้วยตัวอักษรระหว่าง[และeรวม) มันจะเป็นระเบียบถ้า[และ]เป็นตัวอักษรพิเศษที่ไม่ได้เข้าร่วมในการแยกคำที่ควบคุมโดยช่องว่างตามปกติ
[[เป็นคำหลัก - น่าจะเป็นต้นไม้แยกเปลือกของเปลือกหอยที่ต้องการให้คำหลักต้อง