Tại sao dấu ngã (~) không mở rộng khi được sử dụng với đối số CLI bắt đầu bằng dấu gạch ngang?


9

Tôi đã mất vài giờ để chạy máy chủ VNC (x0vncserver) và máy khách từ chối kết nối với tin nhắn lạ

No password configured for VNC Auth

Máy chủ cũng in lỗi này

 SVncAuth:    opening password file '~/.vnc/passwd' failed

Ok, tôi đã lãng phí rất nhiều thời gian cho đến khi tôi nhận ra dấu ngã không được mở rộng bởi trình bao, cũng không phải bởi x0vncserver. Sau đó tôi chạy các bài kiểm tra này

$ echo --PasswordFile=~/.vnc/passwd
--PasswordFile=~/.vnc/passwd

Nhưng

$ echo PasswordFile=~/.vnc/passwd
PasswordFile=/home/tichomir/.vnc/passwd

Tại sao vậy? Tại sao shell từ chối mở rộng dấu ngã nếu đối số bắt đầu bằng dấu gạch ngang? Tôi nghĩ rằng dấu ngã sẽ luôn mở rộng miễn là nó không được trích dẫn, nhưng rõ ràng có một quy tắc khác đi vào hoạt động?



Câu trả lời:


13

Đây là một đặc thù của bashvỏ được mô tả trong hướng dẫn sử dụng của nó:

Bash cũng thực hiện mở rộng dấu ngã trên các từ thỏa mãn các điều kiện của các phép gán biến (như được mô tả ở trên trong PARAMETERS) khi chúng xuất hiện dưới dạng đối số cho các lệnh đơn giản. Bash không làm điều này, ngoại trừ các lệnh khai báo được liệt kê ở trên, khi ở chế độ posix.

Điều này có nghĩa là bash sẽ mở rộng dấu ngã trong PasswordFile=~/.vnc/passwdchuỗi của bạn , vì đó là một đối số echotrông giống như một phép gán biến.

Chuỗi --PasswordFile=~/.vnc/passwdkhông giống như một phép gán biến vì chuỗi --PasswordFilekhông phải là tên biến hợp lệ.

Lưu ý rằng bashkhông làm điều này khi chạy ở chế độ POSIX và các shell khác, như zsh, kshhoặc yashkhông làm điều này theo mặc định ( zshcó một magicequalsubsttùy chọn cho việc mở rộng dấu ngã được thực hiện sau khi các dấu bằng ( =) không được trích dẫn ).

Nếu bạn muốn đảm bảo rằng đường dẫn thư mục chính của người dùng hiện tại được mở rộng đúng cách như là một phần của đối số cho lệnh, hãy sử dụng $HOMEgiá trị thay vì dấu ngã:

echo --PasswordFile="$HOME/.vnc/passwd"

Các "lệnh khai liệt kê ở trên" đề cập đến trong cuốn hướng dẫn được xây dựng trong các lệnh alias, declare, typeset, export, readonly, và local.


1
+1 | Tôi sẽ không nghĩ về điều đó.
LinuxSecurityFreak

Mặc dù lưu ý: bash --posix -c '"export" a=~; printf "%s\n" "$a"'đầu ra ~.
Stéphane Chazelas

2
Lưu ý rằng việc ~được mở rộng alias a=~sẽ là lỗi tuân thủ POSIX (và không hữu ích). Nhưng đó là cách ksh88 đã làm điều đó (điều đó đã thay đổi trong ksh93) và có lẽ là lý do tại sao bash, zsh và pdksh cũng làm điều đó. Tại sao yashđiều đó được viết chống lại thông số POSIX không làm điều đó.
Stéphane Chazelas

Đây là câu trả lời đúng, nhưng cách tiếp cận đúng sẽ chỉ là cung cấp đối số tùy chọn dưới dạng đối số riêng biệt, thay vì hợp nhất với tùy chọn sử dụng =thành một đối số. Sau đó, việc mở rộng dấu ngã là ở đầu của một từ và câu hỏi là tranh luận.
JdeBP

1
@JdeBP, như nó xảy ra, trong trường hợp x0vncserver, x0vncserver --PasswordFile filekhông hoạt động, bạn cần --PasswordFile=file.
Stéphane Chazelas
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.