Tại sao một nhóm lệnh niềng răng cần khoảng trắng sau dấu ngoặc mở trong POSIX Shell Grammar?


10

TL; DR : Tại sao nhóm niềng răng POSIX cần khoảng trắng sau {từ dành riêng nhưng subshell không sau từ dành riêng (?

Ngữ pháp shell POSIX định nghĩa nhóm nẹp và subshell như sau

brace_group      : Lbrace compound_list Rbrace

subshell         : '(' compound_list ')'

Bây giờ, nếu chúng ta đọc theo nghĩa đen, không gian là đáng kể. Điều này có nghĩa là phải có không gian phân định mở và đóng dấu ngoặc và dấu ngoặc đơn như trong

{ echo hello world; }

( echo hello world )

Điều này cũng sẽ phù hợp với các định nghĩa Lệnh Hợp chất :

Mỗi lệnh ghép này có một từ hoặc toán tử điều khiển dành riêng ở đầu và một từ kết thúc hoặc toán tử dành riêng tương ứng ở cuối.

Tuy nhiên, điều không có ý nghĩa là tại sao (list)( list )chỉ hoạt động tốt (không gian đó sau đó (là không bắt buộc), tuy nhiên việc mở rộng niềng răng phải có một không gian hàng đầu, tức là {echo hello;}sẽ không hoạt động.

Tất nhiên, từ dành riêng được coi là từ vỏ sẽ có nghĩa là cần một khoảng trắng sau đó để phù hợp với khái niệm phân tách trường , tuy nhiên định nghĩa tự nó không đề cập đến khoảng trắng. Hơn nữa, nếu {(cả hai đều được coi là các từ dành riêng theo định nghĩa POSIX của lệnh ghép, tại sao chúng được xử lý khác nhau về ký tự khoảng trắng sau các từ dành riêng này? Bây giờ, hướng dẫn ksh (1) hiện trạng thái:

Các từ, là chuỗi các ký tự, được phân cách bằng các ký tự khoảng trắng không được trích dẫn (dấu cách, tab và dòng mới) hoặc ký tự meta (<,>, |,;, &, (và))

Nói cách khác, nó có ý nghĩa rằng ksh sẽ nhận ra (là dấu phân cách từ, trong đó từ đầu tiên sẽ là một lệnh hoặc gán biến. POSIX, tuy nhiên dường như không đề cập đến (như là siêu ký tự. Lời giải thích khả dĩ duy nhất tôi tìm thấy theo ngữ pháp POSIX là nó {được coi là "mã thông báo", trong đó (không được liệt kê là một.

/* These are reserved words, not operator tokens, and are
   recognized when reserved words are recognized. */


%token  Lbrace    Rbrace    Bang
/*      '{'       '}'       '!'   */

Vì vậy, lý do chính xác cho sự khác biệt này là gì?

Ghi chú trả lời được chấp nhận:

  • Đã chuyển dấu kiểm được chấp nhận vào câu trả lời của Isaac vì nó cung cấp cho q uote mẫu chính tiêu chuẩn trực tiếp giải quyết câu hỏi của tôi:

    Chẳng hạn, '(' và ')' là các toán tử điều khiển, do đó không <space>cần thiết trong (danh sách). Tuy nhiên, '{' và '}' là các từ dành riêng trong {list;}, do đó, trong trường hợp này là hàng đầu <space><semicolon>được yêu cầu.

  • Chấp nhận câu trả lời của Kusalananda . Câu trả lời của Kusalananda giải quyết những gì tôi cần, mặc dù chủ yếu theo quan điểm không chính thức và trực quan; nó chỉ ra {là một từ dành riêng và (là toán tử. Michael Homer cũng lưu ý tương tự trong các bình luận - rằng trạng thái định nghĩa Lệnh Hợp chất (nhấn mạnh thêm):

    Mỗi lệnh ghép này có một từ dành riêng hoặc toán tử điều khiển ở đầu

  • {được định nghĩa là từ dành riêng, tương tự forhoặc while, được liệt kê trong Shell Grammar (xem khối mã cuối cùng trong câu hỏi)

  • Mục 2.9 tiểu bang (nhấn mạnh thêm):

    Cụ thể, các biểu diễn bao gồm khoảng cách giữa các mã thông báo ở một số nơi <blank>không cần thiết (khi một trong số các mã thông báo là toán tử).

  • Trong khi tiêu chuẩn không xác định rõ ràng (là một toán tử, (được gọi là toán tử; cụ thể, mục 2.9.2 nói

    Nếu đường ống bắt đầu với từ dành riêng! và lệnh1 là một lệnh con, ứng dụng sẽ đảm bảo rằng (toán tử ở đầu lệnh1 được tách biệt với! bởi một hoặc nhiều ký tự. Hành vi của từ dành riêng! ngay lập tức theo sau (toán tử là không xác định.

  • Câu hỏi về Stack Overflow của Digital Trauma chỉ ra Phần 2.4 về các từ dành riêng:

    Sự công nhận này chỉ xảy ra khi không có ký tự nào được trích dẫn và khi từ được sử dụng là:

    -Từ đầu tiên của một lệnh

  • Như đã đề cập trong câu trả lời của Kusalananda "Các khoảng trắng hiển thị trong ngữ pháp POSIX không phải là khoảng trắng cần có trong dữ liệu đầu vào shell, mà chỉ là một cách hiển thị ngữ pháp. Đó là thực tế rằng dấu ngoặc nhọn là những từ dành riêng ngụ ý rằng chúng phải được bao quanh bởi khoảng trắng "Như Michael Homer đã đề cập trong các bình luận:" Nếu các không gian có ý nghĩa theo cách riêng của chúng, thì chúng cần phải được liệt kê trong sản xuất "

Trường hợp đóng cửa.


3
Nếu các không gian có ý nghĩa theo cách riêng của họ, họ cần phải được liệt kê trong sản xuất.
Michael Homer

2
"Hơn nữa, nếu {(cả hai đều được coi là từ dành riêng theo định nghĩa POSIX của lệnh ghép" "Mỗi lệnh ghép này có một từ dành riêng hoặc toán tử điều khiển ở đầu".
Michael Homer

2
@SergiyKolodyazhnyy Tôi tin rằng anh ta có nghĩa là nếu không gian là quan trọng, ngữ pháp sẽ phải bao gồm một ký tự không gian rõ ràng ( ' '). Thay vào đó, các không gian được ngụ ý bởi những gì các token là từ.
Kusalananda

2
Định nghĩa đặc tả của lớp mã thông báo là ... khó xử, để nói rằng ít nhất. Toàn bộ ngữ pháp là khá khủng khiếp và thông số kỹ thuật trộn lẫn xác định những điều trong văn xuôi (đôi khi là ngầm!), Trong các quy tắc văn xuôi trước ngữ pháp và trong chính ngữ pháp. Thật khó hiểu nếu bạn chưa biết câu trả lời và làm việc ngược lại. Tất cả các quy tắc từ vựng đều được xác định ngược, bởi những gì bắt đầu một mã thông báo mới, thay vì mô tả những gì mã thông báo chứa. Nó chỉ là một mớ hỗn độn xung quanh.
Michael Homer

1
@Sergiy trong ngữ pháp chính thức, một quy tắc sản xuất (hoặc quy tắc sản xuất) mô tả cách bạn có thể tạo ra thứ gì đó từ thứ khác. Xem en.wikipedia.org/wiki/Production_%28computer_science%29 Vì vậy, command : simple_command | compound_command | compound_command redirect_list | function_definition ;là một sản xuất mà nói, nơi bạn có thể có một lệnh, nó có thể là một trong những lệnh đơn giản, chỉ huy hợp chất, hoặc lệnh phức hợp với chuyển hướng, hoặc định nghĩa hàm.
muru

Câu trả lời:


6

Đó là một hạn chế về cách thức mà vỏ phá vỡ các dòng thành mã thông báo.

Shell đọc các dòng từ tệp đầu vào và Theo mục 2 "Giới thiệu Shell" chuyển đổi chúng thành một từ hoặc một toán tử :

  1. Shell phá vỡ đầu vào thành mã thông báo: từ và toán tử

{là một từ dành riêng

Một số từ là từ dành riêng

Từ dành riêng là những từ có ý nghĩa đặc biệt đối với vỏ. Các từ sau đây sẽ được công nhận là từ dành riêng:

! { } case do done elif else esac fi for if in then until while

Các từ, để được công nhận là từ, phải được phân định .

Các từ dành riêng chỉ được nhận ra khi chúng được phân định ...

Chủ yếu là bởi khoảng trống (điểm 7) và bởi các nhà khai thác.

  1. Nếu ký tự hiện tại là <un> không được trích dẫn, mọi mã thông báo có chứa ký tự trước đó được phân cách và ký tự hiện tại sẽ bị loại bỏ.

(là một nhà điều hành

Các nhà khai thác đứng một mình :

trong khi các nhà khai thác là chính họ phân định.

Trong đó "toán tử" là :

Toán tử 3.260

Trong ngôn ngữ lệnh shell, hoặc là một kiểm soát điều hành hoặc một chuyển hướng điều hành.

Toán tử chuyển hướng là :

Toán tử chuyển hướng

Trong ngôn ngữ lệnh shell, mã thông báo thực hiện chức năng chuyển hướng. Đây là một trong những biểu tượng sau:

<     >     >|     <<     >>     <&     >&     <<-     <>

Toán tử điều khiển là :

3.113 Toán tử điều khiển

Trong ngôn ngữ lệnh shell, mã thông báo thực hiện chức năng điều khiển. Đây là một trong những biểu tượng sau:

&   &&   (   )   ;   ;;   newline   |   ||

Phần kết luận

Vì vậy, '(' và ')' là các toán tử điều khiển trong khi '{' '}' là các từ dành riêng.

Và mô tả chính xác của câu hỏi của bạn nằm trong thông số kỹ thuật :

Chẳng hạn, '(' và ')' là các toán tử điều khiển, do đó không cần <dấu cách> trong (danh sách). Tuy nhiên, '{' và '}' là các từ dành riêng trong {list;}, do đó, trong trường hợp này, <space> và <dấu chấm phẩy> hàng đầu là bắt buộc.

Mà chính xác giải thích tại sao một không gian (hoặc một số dấu phân cách khác) được yêu cầu sau a {.

Điều này hợp lệ:

{ echo yes;}

Như thế này:

{(echo yes);}

Điều này:

{(echo yes)}

Hoặc thậm chí này:

{>/dev/tty echo yes;}

Vâng, trích dẫn cuối cùng là chính xác tại chỗ! + 1'ed. Tôi sẽ cần xem lại câu hỏi và câu trả lời ngay bây giờ
Sergiy Kolodyazhnyy

13

Sự khác biệt giữa các dấu ngoặc nhọn và dấu ngoặc đơn là rằng niềng răng (và !) là những từ dành riêng, giống như for, if, thenvv trong khi ngoặc là nhà khai thác kiểm soát. Các từ cần phải được phân tách bằng khoảng trắng.

Điều này có nghĩa là giống như bạn không thể có

foriin*; do

bạn không thể có

{somecommand;} >file

hoặc là

if !somecommand; then

Các khoảng trắng được hiển thị trong ngữ pháp POSIX không phải là khoảng trắng cần có trong dữ liệu đầu vào shell, mà chỉ là một cách hiển thị ngữ pháp. Đó là thực tế rằng các dấu ngoặc nhọn là những từ dành riêng ngụ ý rằng chúng phải được bao quanh bởi khoảng trắng, trong khi dấu ngoặc đơn của một hàm con thì không.


1
Chà, điều này dường như khá nhiều để trả lời nó và tôi thấy nó có ghi "Đặc biệt, các đại diện bao gồm khoảng cách giữa các mã thông báo ở một số nơi không cần thiết (trống> là một trong số các mã thông báo là toán tử)". Chỉ cần một câu hỏi: tiêu chuẩn xác định (là toán tử ở đâu? Nó không nằm trong phần ngữ pháp ít nhất
Sergiy Kolodyazhnyy

@MichaelHomer Ah, "toán tử điều khiển", giống như ;. Cảm ơn vì điều đó.
Kusalananda

Các toán tử điều khiển được liệt kê ở đầu trang con người dưới ĐỊNH NGH DEA. Chúng ta có thể xem xét ()như các toán tử điều khiển như |trong đó cả hai đều liên quan đến các mạng con. Và { }hoạt động trong shell hiện tại và không thể liên quan đến một subshell.
glenn jackman

@Kusalananda Tìm thấy nó, phần 2.9.2: "Nếu đường ống bắt đầu bằng từ dành riêng! Và lệnh1 là một lệnh con, ứng dụng sẽ đảm bảo rằng (toán tử ở đầu lệnh1 được tách ra khỏi! Bởi một hoặc nhiều < trống> ký tự. Hành vi của từ dành riêng! ngay lập tức theo sau (toán tử là không xác định. "Không phải là một định nghĩa rõ ràng nhưng tiêu chuẩn gọi nó là (toán tử
Sergiy Kolodyazhnyy

@glennjackman Mặc dù sự thật là các đường ống liên quan đến các mạng con, nhưng đó không phải là loại định nghĩa có vẻ phù hợp. Tiêu chuẩn cũng đề cập rằng trong một số triển khai, đường ống chạy trong môi trường thực thi shell hiện tại là ổn (và tôi biết đó là trong tiêu chuẩn, bởi vì tôi đã thấy văn bản ngày hôm qua và tìm kiếm nó ngay bây giờ). Tuy nhiên, đề nghị của bạn đã chỉ cho tôi tìm trích dẫn mà tôi đã nhận xét ở trên, trong đó ít nhất là tiêu chuẩn gọi nó là toán tử mặc dù không xác định rõ ràng nó là một
Sergiy Kolodyazhnyy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.