ตัวอย่างเช่นคำสั่งต่อไปนี้ใช้ไม่ได้:
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
รวม) มันจะเป็นระเบียบถ้า[
และ]
เป็นตัวอักษรพิเศษที่ไม่ได้เข้าร่วมในการแยกคำที่ควบคุมโดยช่องว่างตามปกติ
[[
เป็นคำหลัก - น่าจะเป็นต้นไม้แยกเปลือกของเปลือกหอยที่ต้องการให้คำหลักต้อง