Tại sao khoảng trắng đôi khi cần thiết xung quanh siêu nhân vật?


543

Vài tháng trước tôi đã xăm một quả bom ngã ba trên cánh tay của mình, và tôi đã bỏ qua các khoảng trắng, bởi vì tôi nghĩ nó trông đẹp hơn nếu không có chúng. Nhưng với sự thất vọng của tôi, đôi khi (không phải lúc nào cũng vậy) khi tôi chạy nó trong một cái vỏ, nó không khởi động một quả bom ngã ba, nhưng nó chỉ đưa ra một lỗi cú pháp.

bash: syntax error near unexpected token `{:'

Hôm qua nó đã xảy ra khi tôi cố chạy nó trong vỏ Bash của một người bạn , và sau đó tôi đã thêm khoảng trắng và nó đột nhiên hoạt động, :(){ :|:& };:thay vì:(){:|:&};:

Liệu khoảng trắng có vấn đề; Tôi đã xăm một lỗi cú pháp trên cánh tay của mình?!

Nó dường như luôn luôn hoạt động trong zsh , nhưng không phải trong Bash.

Một câu hỏi liên quan không giải thích bất cứ điều gì về khoảng trắng, đó thực sự là câu hỏi của tôi; Tại sao khoảng trắng cần thiết để Bash có thể phân tích chính xác?


6
Tôi đã đăng câu hỏi tương tự ở đây (không bao gồm phần hình xăm).
Benoit

3
Ngoài ra, dấu hai chấm (:) không thể được sử dụng làm tên hàm (xem: pubs.opengroup.org/onlinepub/9699919799/utilities/, ) ... FreeBSD's / bin / sh thậm chí còn báo lỗi về điều này ...
Martin Tournoij

5
@Carpetsmoker: Tôi không chắc nó có liên quan như thế nào. Câu hỏi này là về Bash.
Dennis

Câu trả lời:


267

Có một danh sách các ký tự phân tách mã thông báo trong BASH. Những nhân vật được gọi là metacharacters và họ là |, &, ;, (, ), <, >, không giantab . Mặt khác, dấu ngoặc nhọn ( {}) chỉ là các ký tự bình thường tạo nên từ.

Bỏ qua không gian thứ hai trước }sẽ làm, vì &là một metacharacter. Do đó, hình xăm của bạn nên có ít nhất một nhân vật không gian.

:(){ :|:&};:

35
Giải pháp dễ dàng: di chuyển phần đầu tiên của taoo sang bên trái và ghép da giữa hai phần.

23
Tôi thích thuật ngữ này, on the other hand... ý định chơi chữ? ;): D (Xin lỗi, vì đã tắt bình luận chủ đề.)
anishsane

4
Nhưng điều này là khác nhau cho zsh? Zsh khác nhau theo cách nào?
tfogo

2
Giải thích tốt, ngoại trừ đó {}các từ khóa shell trong bối cảnh này. Chỉ khi chúng không được công nhận như vậy - do thiếu không gian / siêu nhân vật xung quanh - thì chúng mới được coi là một phần nghĩa đen của từ mà chúng trở thành một phần của. (Và sau đó là mở rộng cú đúp, xảy ra trong một bối cảnh khác.)
mkuity0

2
@DmitriChubarov Niềng răng được phép trong các tên lệnh (bao gồm các hàm : {foo} () { echo hello; }. "Tên", như được định nghĩa trong bash"một từ chỉ bao gồm các ký tự chữ và số và gạch dưới, và bắt đầu bằng một ký tự chữ cái hoặc dấu gạch dưới", chỉ áp dụng cho các tên biến.
chepner

82

Chỉ cần xăm một

#!/bin/zsh

shebang ở trên nó và bạn sẽ ổn thôi.


6
Nếu chúng tôi kén chọn, shebang hoàn toàn không hoạt động, vì vỏ, hy vọng zsh, ở chế độ tương tác, bằng chứng là bằng lời nhắc ...
SzG

50

Niềng răng giống như các từ khóa kỳ lạ hơn các ký hiệu đặc biệt và không cần khoảng trắng. Điều này khác với dấu ngoặc đơn, ví dụ. Đối chiếu:

(ls)

hoạt động và:

{ls}

mà tìm kiếm một lệnh có tên {ls}. Để làm việc, nó phải là:

{ ls; }

Dấu chấm phẩy dừng dấu ngoặc đóng được lấy làm tham số ls.

Tất cả bạn phải làm là nói với mọi người rằng bạn đang sử dụng phông chữ tỷ lệ với một ký tự không gian khá hẹp.


12
@DmitriChubarov - đó là một mẹo rất lén lút, sử dụng một ý nghĩa hoàn toàn khác của niềng răng. Nó mở rộng danh sách các giá trị được phân tách bằng dấu phẩy, trong trường hợp này chỉ là ls.
Peter Westlake

7
Nhưng cậu bé thì bạn sẽ có hình xăm cho đến hết đời! Bạn đánh dấu mình là một mọt sách cho mọi thời đại! Và sau đó bạn thậm chí không thể có được nó ngay trước khi nó được khâu? Tôi đoán đó là hai bước xa hơn tôi đoán ;-) Không xúc phạm, bạn ạ, tôi chỉ đang tự hỏi.
Alfe

14
@Alfe Tôi đã thử nó trước khi tôi xăm nó, nhưng tôi đã thử nó trong zsh của tôi, tôi nghĩ rằng nó có cùng phân tích cú pháp như bash. Ngu ngốc của tôi, nhưng tôi sẽ chỉ nói với mọi người rằng đó là zsh. :)
spydon

20
@spydon Hoặc bạn nói với họ rằng bạn đã để trống không gian nhằm mục đích để mọi người sao chép lệnh từ hình xăm của bạn sẽ không vô tình chạy nó và làm hỏng máy của họ;)
chọc vào

4
Xin chào, nếu nó hợp lệ trong zsh, tại sao không thêm #! / Bin / zsh ngay phía trên nó (hoặc trước nó)? Dù sao đi nữa, đó là cách tốt để xác định vỏ trước.
Adam Miller

41

Mặc dù không dễ dàng nhìn thấy trong phông chữ tatoo, nhưng thực sự có Dấu Byte-Order (BOM) giữa dấu ngoặc và dấu hai chấm (bạn có thể đã bị say đủ khi bạn nhận được hình xăm mà bạn không nhận thấy, nhưng nó thực sự ở đó) . Điều này để lại ba khả năng rõ ràng:

  1. Bạn đã không nhập được BOM khi bạn sao chép mã. Kết quả là một ứng dụng rõ ràng của GIGO. Shell đơn giản là không nhận ra BOM không có trong phiên âm thất bại của bạn.
  2. Vỏ của bạn quá cũ. Nó không nhận ra các ký tự Unicode, do đó BOM (và có thể là tất cả các ký tự Unicode khác) đang bị bỏ qua hoàn toàn, mặc dù BOM ở bất cứ đâu nhưng phần đầu của tệp được coi là không gian không có độ rộng, không phá vỡ .
  3. Vỏ của bạn quá mới. Việc sử dụng BOM làm ZWNBS không được chấp nhận và các tác giả đã triển khai phiên bản Unicode trong tương lai, trong đó việc sử dụng này không còn được cho phép.

40

và sau đó tôi đã thêm khoảng trắng và nó đột nhiên hoạt động ...

Đó là vì cách phân tích vỏ. Bạn cần một khoảng trắng sau khi định nghĩa hàm bắt đầu, tức là sau {.

foo() { echo hey& }
foo() { echo hey&}
foo(){ echo hey&}

có giá trị. Mặt khác,

foo() {echo hey&}

không phải.


Bạn thực sự cần một hình xăm như thế này:

nhập mô tả hình ảnh ở đây


Từ nguồn :

  /* We ignore an open brace surrounded by whitespace, and also
     an open brace followed immediately by a close brace preceded
     by whitespace.  */

Bỏ qua một khoảng trắng sau các {nguyên nhân {echosẽ được hiểu là một mã thông báo duy nhất.


Một hình thức tương đương của

:(){ :|:& };:

sẽ là

:(){
:|:& };:

Lưu ý rằng không có khoảng trắng sau {trong phiên bản thay thế, nhưng ngắt dòng làm cho trình bao nhận ra {là mã thông báo.


"Bỏ qua một khoảng trắng sau {làm cho {echo được hiểu là một mã thông báo duy nhất." - vậy trình phân tích cú pháp có tin rằng nó đã gặp phải một lệnh được gọi {echotrước khi nó đạt đến một dấu ngoặc mở bắt buộc không?
Giô-na
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.