Tại sao các bài kiểm tra bash rất kén chọn về khoảng trắng?


7

Là một lập trình viên Java chủ yếu, tôi thấy bash if- thenxây dựng khá khó hiểu, đặc biệt là về khoảng trắng. Bất cứ ai có thể giải thích tại sao cái thứ nhất hoạt động, nhưng không phải cái thứ hai hay thứ ba?

#works
if [ -n $1 ]; then echo "parameterized"; fi

#output: ./links: Zeile 1: [-n: Kommando nicht gefunden.
if [-n $1 ]; then echo "parameterized"; fi

#output: ./links: Zeile 1: [: Fehlende `]'
if [ -n $1]; then echo "parameterized"; fi

5
Để lại một biến không được trích dẫn là toán tử split + global trong shell. Có rất ít trường hợp bạn thực sự muốn để lại các biến không được trích dẫn.
Stéphane Chazelas

Câu trả lời:


17

Sự không nhất quán phần lớn là do lý do lịch sử.

Việc sử dụng dấu ngoặc làm lệnh điều kiện được đưa ra sau khi sử dụng dấu ngoặc trong các mẫu ký tự đại diện. Vì vậy, tại thời điểm đó [ -n foo ]xuất hiện, [foo]đã có nghĩa là một tập tin có tên là fhay o. Mặc dù ít sử dụng toán tử ngoặc trong thực tế sẽ mâu thuẫn với sử dụng thực tế của dấu ngoặc trong ký tự đại diện, các tác giả đã chọn không mạo hiểm phá vỡ các tập lệnh hiện có bằng cách thay đổi cú pháp. Sự lựa chọn thiết kế này cũng làm cho việc thực hiện dễ dàng hơn: ban đầu [được thực hiện như một lệnh bên ngoài, điều này không thể được thực hiện nếu không gian sau [đó là tùy chọn. (Các hệ thống hiện đại vẫn có [một lệnh bên ngoài nhưng hầu như tất cả các hệ vỏ hiện đại cũng được tích hợp sẵn.)

Vì những lý do tương tự, mã làm việc trên mạng của bạn thực sự không chính xác trong hầu hết các trường hợp. $1không có nghĩa là giá trị của tham số 1 QUAN: nó có nghĩa là lấy giá trị của tham số 1, chia nó thành các từ riêng biệt ở khoảng trắng (hoặc bất kể giá trị của IFSnó là gì) và diễn giải từng từ dưới dạng mô hình toàn cầu. Cách viết ra giá trị của tham số 11 yêu cầu dấu ngoặc kép : "$1". Xem Khi nào cần trích dẫn kép? cho nitty-gritty. Bạn không cần phải hiểu điều này; tất cả những gì bạn cần nhớ là: luôn đặt dấu ngoặc kép xung quanh các thay thế "$foo"và thay thế lệnh"$(foo)" . Như vậy:

if [ -n "$1" ]; then 

Trong bash, ksh và zsh, nhưng không phải trong sh đơn giản, bạn cũng có thể sử dụng dấu ngoặc kép. Dấu ngoặc đơn [ … ]được phân tích cú pháp như một lệnh thông thường (và thực sự [là một lệnh thông thường, mặc dù thường được xây dựng). Dấu ngoặc kép là một cấu trúc cú pháp riêng biệt và bạn có thể bỏ qua dấu ngoặc kép hầu hết thời gian.

if [[ -n $1 ]]; then 

Tuy nhiên, có một ngoại lệ: [[ "$foo" = "$bar" ]]để kiểm tra xem hai biến có cùng giá trị yêu cầu dấu ngoặc kép $barhay không, nếu không thì $barđược hiểu là mẫu ký tự đại diện. Một lần nữa, thay vì nhớ các chi tiết, bạn cũng có thể sử dụng dấu ngoặc kép mọi lúc.


+1 cho giải thích ngắn gọn súc tích về '$ 1 không có nghĩa là "giá trị của tham số 1" - đây là điều quan trọng cần nói về điều đó, và nitty-gritty mà bạn liên kết thực sự có thể được cải thiện bằng cách bắt đầu nó với những gì bạn nói ở đây
Don nở

11

trong thực tế, ký tự [là một lệnh shell tích hợp để đánh giá đối số cho đến khi đối số ]
bash sử dụng đối số tách biệt bởi khoảng trắng, vì vậy nếu bạn muốn gọi, [bạn cần đặt một khoảng trắng hoặc nó sẽ cố gắng thực thi lệnh [-nkhông phải là hàm hoặc nhị phân bash biết (ít nhất là cho đến khi bạn tự tạo một cái).

Khi bạn viết [-n $1 ]nó có nghĩa là
[-nvới các đối số $1]không có ý nghĩa
và nếu bạn đặt [ -n $1]nó có nghĩa là
[với đối số -n$1]thiếu ]đối số của hàm [để nó không thể đánh giá biểu thức của bạn


Hừm, tôi đã sử dụng nó trong nhiều năm, chưa bao giờ nghĩ tại sao nó lại theo cách này mà không phải bất kỳ thứ gì khác. Điều này làm cho ý nghĩa hoàn toàn. Cảm ơn bạn đã giáo dục.
Marcin

@Marcin Tôi thường tự hỏi mình câu hỏi và gần đây tôi đã đọc một câu trả lời tạo về cd ở đâu? và sau đó tôi hiểu tại sao một không gian là một nghĩa vụ, bởi vì không có nó là vô nghĩa: D dù sao tôi cũng rất vui vì điều này giúp bạn
Kiwy
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.