เหตุใดลำดับจึงสำคัญในการประมวลผลคำสั่ง bash เหล่านี้


10

ดูเหมือนจะมีความไม่สอดคล้องกันบางอย่างที่ฉันไม่สามารถเข้าใจเกี่ยวกับเปลือก bash

หากฉันดำเนินการ:

ls;date;time

ผลลัพธ์ของแบบสอบถามทั้งสามจะแสดงตามลำดับ

อย่างไรก็ตามในการแลกเปลี่ยนวันที่และตำแหน่งเวลาข้อความแสดงข้อผิดพลาดจะปรากฏขึ้น

ดังนั้นถ้าฉันดำเนินการ:

ls;time;date

bash: syntax error near unexpected token 'date'เกิดข้อผิดพลาดพูดว่า:

มีคนอธิบายเรื่องนี้ได้ไหม


ปัญหาของคุณอยู่บนVStime;date date;timeดูเหมือนว่าจะมีปัญหากับไปป์ไลน์ในbashและอักขระตัวสุดท้ายที่สร้างขึ้นด้วยtimeเอาต์พุต ผลการทดสอบในโปรแกรมจำลองเทอร์มินัลที่แตกต่างกันคือ: - [Bash] $ date; time # [OK] $ time; date # [ NotOK ] bash: ข้อผิดพลาดทางไวยากรณ์ใกล้โทเค็นที่ไม่คาดคิด `date '$ time # ข้อผิดพลาดเท่านั้น ผลของวันที่ใด ๆ - [Csh] $ date; time # [OK] $ time; date # [OK] - [Tcsh] $ date; time # [OK] $ time; date # [OK] - [Ksh] $ date; time # [ ตกลง] $ time; date # [OK]
Mostafa Shahverdy

ฉันได้อัพเดตคำตอบของฉันพร้อมคำอธิบายสำหรับข้อความแสดงข้อผิดพลาด โปรดตรวจสอบว่านี่เป็นคำตอบที่คุณต้องการ
zwets

คำตอบ:


10

timeคำสั่งในท่อของคุณไม่ได้เป็น/usr/bin/timeไบนารี แต่ทุบตีtimeในตัว เปรียบเทียบกับman time help timeข้อผิดพลาดที่คุณเห็นคือการทุบตีล้มเหลวในการแยกวิเคราะห์timeอาร์กิวเมนต์ สิ่งนี้จะต้องปรากฏหรือขึ้นบรรทัดใหม่ มันเป็นบรรทัดใหม่ในตัวอย่างแรกของคุณ แต่ขาดไปในครั้งที่สอง

ในทางตรงกันข้ามถ้าคุณต้องวิ่ง

ls;date;'time'

หรือ

ls;'time';date

โดยที่เครื่องหมายคำพูดรอบ ๆ'time'เพิกถอนสถานะเป็นคำที่สงวนไว้แล้ว bash จะไม่มีปัญหาในการแยกบรรทัด ตอนนี้แยกวิเคราะห์คำสั่งสามรายการในรายการซึ่งจะดำเนินการตามลำดับและ/usr/bin/timeจะรายงานข้อผิดพลาดการใช้งานในกรณีใดกรณีหนึ่ง

ภาคผนวก

มีข้อสังเกตว่าแม้ว่าจะtime ; dateทำให้เกิดข้อผิดพลาด แต่time ; ; dateก็ไม่ได้ สาเหตุที่น่าจะเป็นที่ถูกตีความโดยทุบตีเป็นไปเทียบเท่าtime ; time <newline>การแสดงออกtime ; ; dateจะแยกกันแล้วเป็นรายชื่อของและtime ;date

สิ่งนี้สอดคล้องกับการสังเกตว่าtime ;และtime ; ;ถูกต้องตามกฎหมายเช่นกันส่วนที่สองจะถูกแยกเป็นรายการซิงเกิลที่มีtime ;ตามด้วยเซมิโคลอนเผื่อเลือกที่อนุญาตหลังจากรายการ

อีกวิธีหนึ่งในการอธิบายว่าทำไมtime ; dateข้อผิดพลาดbash: syntax error near unexpected token 'date'คือให้timeใช้เครื่องหมายอัฒภาคแยกมันออกจากdateกัน มันสามารถทำได้เพราะtimeเป็นคำสงวนทุบตี


ขอบคุณสำหรับคำอธิบายที่ดี! แต่แล้วพฤติกรรมนี้อีกครั้งดูเหมือนเป็นข้อบกพร่องสำหรับฉัน: timeควรอนุญาตให้ใช้คำสั่ง NULL และเครื่องหมายอัฒภาคควรคั่นรายการดังนั้น IMO timeคำสั่งไม่ควร "ใช้" เครื่องหมายอัฒภาคหลังจากนั้น คำสั่ง builtin อื่น ๆ (ซึ่งสามารถรับอาร์กิวเมนต์) ไม่แสดงพฤติกรรมประเภทนี้
จัด

@arrange แทรกซ้อนคือเวลาที่ไม่อนุญาตให้มีคำสั่ง null (ที่จะมี disambiguated ทุกอย่าง) ก็อนุญาตให้ขึ้นบรรทัดใหม่แทนคำสั่ง ดังนั้นtime;dateการตีความใด ๆ อย่างไรก็ตาม time ;และtime ; ;จากนั้นก็จะผิดกฎหมาย มันสามารถถกเถียงกันว่าtimeพฤติกรรมของมันเป็นข้อผิดพลาดหรือไม่มีเอกสาร (มันเป็นความสอดคล้องภายใน) แต่รายงานข้อผิดพลาดจะอยู่ในสถานที่แน่นอน คุณยินดีที่จะยื่นเรื่องนี้หรือไม่?
zwets

ดีฉันมองไปที่แหล่งที่มา (bash4.2: parse.y: เส้น 1205-1221) และมีมันบอกว่าแล้วก็ไม่ได้โดยtime by itself can time a null command $$ = make_simple_command (x, (COMMAND *)NULL);สำหรับการบันทึกข้อผิดพลาดฉันไม่แน่ใจ 8)
จัด

ควรสังเกตว่าปัญหานี้มีเฉพาะของ bash การทำtime ; dateผลงานในksh93และmkshไม่มีข้อผิดพลาดแม้ในksh ที่มีtimeคำหลัก
Sergiy Kolodyazhnyy

2

ทุบตีถือว่าในตัวtimeเป็นกรณีพิเศษเมื่อแยกบรรทัดคำสั่ง

ดังที่สามารถอ่านได้ใน bash manpage บรรทัดที่พิมพ์ถูกแบ่งออกเป็นรายการแรก:

pipeline ; pipeline

โดยที่ไปป์ไลน์:

[time [-p]] [ ! ] command [ [|⎪|&] command2 ... ]

หรือในกรณีของเราเพียง:

time command

เช่นถ้าเวลามีอยู่แล้วคำสั่งจะต้องเป็นปัจจุบัน

[มีกรณีพิเศษที่อนุญาตให้timeขึ้นบรรทัดใหม่ แต่ไม่สามารถใช้งานได้ที่นี่]

ดังนั้นในกรณีของเราเรามี:

time;date

ถูกแบ่งออกเป็นสองท่อ:

1. time
2. date

และไปป์ไลน์ 1 นั้นมีรูปแบบไม่ดีเนื่องจากเราtimeไม่มีคำสั่ง ดังนั้นข้อผิดพลาด

โปรดทราบว่าบรรทัดคำสั่งtimeไม่ทำงานที่นี่:

$ /usr/bin/time;date
Usage: /usr/bin/time [-apvV] [-f format] [-o file] [--append] [--verbose]

ทุบตีวิเคราะห์สิ่งนี้ตามที่คาดไว้ออกเป็น 2 ท่อ:

1. /usr/bin/time
2. date

และ/usr/bin/timeจากนั้นก็ปฏิเสธที่จะทำงานกับข้อโต้แย้งใด ๆ โปรดทราบว่านี่เป็นข้อผิดพลาดจาก/usr/bin/timeไม่ใช่ข้อผิดพลาดจากการทุบตี

เหตุผลที่ back-tick ใช้งานได้เนื่องจาก back-tick หยุดtimeถูกตีความว่าเป็นองค์ประกอบพิเศษภายในไปป์ไลน์

เช่นกับ back-tick:

`time`;date

มันแยกเป็นสองท่อ:

1. `time`
2. date

โปรดจำไว้ว่าในกรณีของเราคือ:

[time] command

และปัญหาแรกคือเราtimeไม่มีคำสั่งซึ่งไม่ได้รับอนุญาต แต่ตอนนี้เรามีคำสั่ง:

`time`

หากไม่มีเครื่องหมายข้างtimeหลังหมายความว่าtimeถูกตีความว่าเป็นคำสั่งไม่ใช่คำก่อนหน้า

ดังนั้นทุบตีจึงสร้างบิวอินtimeโดยไม่มี args ซึ่งเป็นที่ยอมรับ มันไม่สร้างผลลัพธ์และเราไม่เห็นข้อผิดพลาด

โปรดทราบว่า:

`time`

จริง ๆ แล้วเรียกใช้ผลลัพธ์ของtimeบิวด์อินเช่นมันรันอะไรก็ตามที่timeบิวด์อินสร้างบน stdout แต่เนื่องจากtimeตัวมันเองไม่ได้เขียนอะไรเลยเพื่อ stdout มันจึงดูเหมือนใช้งานได้

ในที่สุดมันก็ถูกตั้งข้อสังเกตว่างานนี้:

time ; ; date

ซึ่งฉันไม่สามารถอธิบายได้อย่างน่าเศร้า :)


ฉันคิดว่าคำอธิบายของคุณดีกว่า แต่มันก็ดูแปลกสำหรับฉัน ;dateให้bash: syntax error near unexpected token ;แต่time ;dateให้bash: syntax error near unexpected token dateดังนั้นดูเหมือนทุบตีไม่ปฏิบัติตามคำสั่งหลังจากเวลา builtin เป็น "; date" น่าสนใจใช้time ; ; dateงานได้
จัดการ

yup ขอบคุณ @ จัดเรียงมันค่อนข้างแปลก ฉันจะอัปเดตคำตอบเล็กน้อย
cdmackay

ตกลง @ จัดเรียงได้เขียนใหม่ ยังไม่สามารถอธิบายครั้งสุดท้ายของคุณแม้ว่า ... ถอนหายใจ
cdmackay

@cdmackay คุณกำลังผสม backticks และเครื่องหมายคำพูด โดยการอ้างอิง 'time'มันสูญเสียความหมายเป็นคำสงวน Backtickingมันทำให้มันทำงานใน subshell ที่เอาท์พุทได้รับการ spliced ​​ในคำสั่ง สิ่งนี้ไม่เกี่ยวกับการสนทนา ตามจริงแล้วตัวอย่างของคุณ`time\';dateพิสูจน์ข้อเรียกร้องของคุณตรงกันข้าม: สิ่งนี้ควรให้ข้อผิดพลาดโดยเหตุผลของคุณเพราะ/usr/bin/timeต้องมีการโต้แย้ง เหตุผลที่มันไม่ได้เป็นเพราะใน subshell ที่มันดำเนินการมันเป็นคำที่สงวนไว้timeอีกครั้ง
zwets

@arrange ทั้งคู่เป็นข้อผิดพลาดทางไวยากรณ์และทั้งคู่รายงานว่าอยู่ใกล้สถานที่เดียวกันดังนั้นฉันจึงไม่เห็นความขัดแย้งที่นั่น เมื่อเข้าสู่ข้อผิดพลาดทางไวยากรณ์คุณจะไม่สามารถคาดหวังให้โปรแกรมแยกวิเคราะห์รู้ทางออก หากคุณต้องการให้โปรแกรมแยกวิเคราะห์คุณต้องรู้ว่าไม่เพียง แต่ไวยากรณ์ตามกฎหมาย แต่ยังรวมถึงไวยากรณ์ของการสร้างที่ผิดกฎหมายทุกครั้งที่เป็นไปได้ซึ่งเป็นไปไม่ได้ตามคำจำกัดความ
zwets
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.