Tên biến shell có thể bao gồm dấu gạch nối hoặc dấu gạch ngang (-) không?


38

Tôi không thể sử dụng -trong các biến trong shell. Có cách nào để có thể sử dụng nó không, bởi vì tôi có một tập lệnh phụ thuộc vào các biến được đặt tên như vậy:

$export a-b=c
-bash: export: `a-b=c': not a valid identifier

$export a_b=c

Đầu tiên ném lỗi đã cho và thứ hai hoạt động tốt.


trang web chéo có thể trùng lặp của: stackoverflow.com/questions/2821043/ từ
Ciro Santilli 改造 心 心

Vỏ thường không cho phép tên biến như vậy. Bạn sẽ phải bỏ qua trình bao, có lẽ ngay cả với chương trình C tùy chỉnh đang tải các biến vào môi trường của bạn. Bạn không thể sửa lỗi sai này (thậm chí có thể có rủi ro bí mật)?
vonbrand

Câu trả lời:


47

Tôi chưa bao giờ gặp một vỏ kiểu Bourne cho phép -trong một tên biến. Chỉ các chữ cái ASCII (của cả hai trường hợp) _và chữ số được hỗ trợ và ký tự đầu tiên không được là chữ số.

Nếu bạn có một chương trình yêu cầu biến môi trường không khớp với các giới hạn shell, hãy khởi chạy nó với envchương trình.

env 'strange-name=some value' myprogram

Lưu ý rằng một số shell (ví dụ: dash hiện đại , mksh, zsh) xóa các biến có tên mà chúng không thích từ môi trường. ( Shellshock đã khiến mọi người thận trọng hơn về tên biến môi trường, do đó, các hạn chế có thể trở nên chặt chẽ hơn theo thời gian, không dễ cho phép hơn.) Vì vậy, nếu bạn cần chuyển một biến có tên đặc biệt cho chương trình, hãy truyền trực tiếp không có vỏ ở giữa ( env 'strange-name=some value' sh -c'…; myprogram'có thể hoặc không thể hoạt động).


Công việc ngắn hạn.
Jesse Glick

4
@JlieGlick Có nó. (Nhận xét của bạn sẽ hữu ích nếu bạn xác định rằng không hoạt động của Sony: với dữ liệu nào? Hiệu ứng thay vì hiệu ứng mong muốn là gì và nếu bạn nói việc triển khai nào của envbạn được sử dụng trên hệ điều hành nào.)
Gilles 'dừng lại ác '

Lấy làm tiếc. Ubuntu Yakkety với tất cả các bản cập nhật, envtừ coreutils, shtừ dash: env 'with-dashes=value' bash -c 'env | fgrep dashes'hoạt động nhưng env 'with-dashes=value' sh -c 'env | fgrep dashes'không in được gì. Đó là, envbản thân là tốt, nhưng Dash dường như để ngăn chặn đặc biệt các biến này. Do đó, nếu chương trình được đề cập được khởi chạy thông qua trình bao bọc với tiêu #!/bin/shđề điển hình , không có cách rõ ràng nào để vượt qua trong các biến như vậy. ví dụ giải pháp
Jesse Glick

@JlieGlick Đó là dấu gạch ngang loại bỏ biến. Bạn phải sử dụng envgần hơn với trang web gọi của chương trình cần tên biến này, không có vỏ ở giữa. Dash không đơn độc trong việc loại bỏ các biến có tên mà nó không thích.
Gilles 'SO- ngừng trở nên xấu xa'

1
@JlieGlick Đúng là một số thứ đã từng hoạt động có thể không còn hoạt động nữa, mặc dù: kể từ shellshock , mọi người đã trở nên bảo thủ hơn về tên biến và thực tế đã thay đổi kể từ khi tôi viết câu trả lời này (mặc dù không phải là hậu quả của Shellshock, nhưng để tránh một lỗi dọc theo cùng một dòng). Tôi đã thêm một ghi chú cho câu trả lời của tôi.
Gilles 'SO- ngừng trở nên xấu xa'

15

Điều đó là không thể ở Bash.

Từ phần Định nghĩa trong trang hướng dẫn của bash:

tên Một từ chỉ bao gồm các ký tự chữ và số và dấu 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. Cũng được gọi là một định danh.

Từ phần Thông số trong trang hướng dẫn của bash:

Một tham số là một thực thể lưu trữ các giá trị. Nó có thể là tên, số hoặc một trong các ký tự đặc biệt được liệt kê bên dưới trong Thông số đặc biệt. Một biến là một tham số được biểu thị bằng một tên.


2
+1 để chứng minh tính hữu dụng của các trang man một lần nữa
ktf

2
Bài viết cũ tôi biết nhưng, tôi muốn chỉ ra rằng những người mới vào trang có thể khá khó hiểu. Tôi vẫn có những lúc tôi cần tìm kiếm những giải thích / ví dụ tốt hơn. Bất cứ ai cũng sẽ nói dối nếu họ nói điều đó không bao giờ xảy ra với họ.
TCZ8

1
@ TCZ8 Những người duy nhất đã nói với tôi rằng họ nghĩ các trang của con người là 'mật mã' là cùng loại người không đọc thông báo lỗi và chỉ đọc lướt mọi thứ, bỏ qua những gì họ cần đọc.
Miles Rout

13

Bạn có thể truy cập một biến gạch nối bằng cách sử dụng một tham chiếu gián tiếp.

$ env 'my-hyphenated-variable=hello' /bin/bash
$ name='my-hyphenated-variable'
$ echo ${!name}
hello

1
Tôi chưa bao giờ nghe về chức năng này cho đến khi đọc bình luận này. Cung cấp một giải pháp dễ dàng hơn nhiều cho tôi so với câu trả lời được chấp nhận.
DrStrangepork

7
Hành vi này đã bị vô hiệu hóa trong các phiên bản mới hơn của bash. Xem stackoverflow.com/questions/36989263/ trên để biết phân tích kỹ lưỡng về tình huống.
Nicolas Dudebout

6

Nếu tập lệnh của bạn phụ thuộc vào việc tên biến có dấu gạch nối, đó là lỗi lập trình. Nếu nó thuận tiện cho bạn vì các công cụ mà bạn thường xuyên sử dụng để có tên biến chứa dấu gạch nối, bạn có thể phải tìm hiểu thêm và các công cụ khác nhau.

Bạn đã thử sử dụng tr để chuyển đổi các dấu gạch nối thành dấu gạch dưới chưa?

hyphenated_name="a-b"
unhyphenated_name=$(echo $hyphenated_name | tr '-' '_')
declare -x $unhyphenated_name="some value"

Bash không cho phép '-' xuất hiện trong tên hàm. Tôi làm điều này tất cả các thời gian. Ví dụ:

function foo-bar() {
   echo "$@"
}

2

Ký tự dash ( -) là ký tự ngắt và không được phép là một phần của tên biến. Có nhiều cách để hack cái này với các biến được trích dẫn, nhưng việc phân tích cú pháp của nó thực sự có vấn đề. Ngoài ra còn có các ký tự khác có ý nghĩa đặc biệt trong ngữ cảnh của các tên biến trong bash, đáng chú ý là dấu ngoặc nhọn, dấu ngoặc đơn, ký tự toán tử và dấu ngoặc kép. (ví dụ {}()=+-&'"và nhiều hơn nữa)

Tôi sẽ đề nghị rằng thực tế bạn cần tìm một mô hình khác để xây dựng kịch bản của mình. Bạn có thể có ý tưởng từ các ngôn ngữ khác về "tên biến khác nhau". Điều này thường không phải là một ý tưởng tốt trong các kịch bản shell.

Nếu bạn chỉnh sửa câu hỏi này hoặc đặt câu hỏi mới với chi tiết về bối cảnh của bạn và những gì bạn đang cố gắng thực hiện, chúng tôi có thể đề xuất một cách hay để viết kịch bản.


2

Hướng dẫn Bash định nghĩa một "tên" là:

Một "từ" chỉ bao gồm các chữ cái, số và dấu gạch dưới và bắt đầu bằng một chữ cái hoặc dấu gạch dưới. 'Tên được sử dụng làm tên biến và hàm shell. Cũng được gọi là một "định danh".

Vì vậy, bạn không thể sử dụng dấu gạch nối trong tên.


0

Hầu hết các shell chỉ hỗ trợ az, AZ, 0-9 và _ cho các kiểu chữ. Đọc mục thứ hai trong trang này .


0

Bạn có thể chơi với env và sed.

Ví dụ, tôi cần đọc biến này 'ELASTICSEARCH_CLUSTER-NODES'.
Lệnh env xuất ra điều này:

~ $ env
ELASTICSEARCH_CLUSTER-NODES=elasticsearch:9200
JAVA_ALPINE_VERSION=8.212.04-r0
HOSTNAME=17eb9e7fec4c
...

Vì vậy, để trích xuất các biến:

ESHOST=`env | sed -n 's/ELASTICSEARCH_CLUSTER-NODES=\(.*\)/\1/p'`

-1

Tôi tin rằng chỉ các chữ cái, số và dấu gạch dưới mới được phép cho các biến bash. Đây là trường hợp trong nhiều ngôn ngữ lập trình (javascript là một ngoại lệ).

Tôi khuyên bạn không nên có tập lệnh của mình phụ thuộc vào các loại tên biến đó.

Thực tế, bạn nên cố gắng lập trình theo cách mà bạn có thể thay thế tên biến bằng tên khác và nó không tạo ra sự khác biệt. Nói chung, tên biến nên mô tả những gì biến chứa. Điều này làm cho nó dễ dàng hơn để gỡ lỗi; nếu không phải cho bạn, thì đối với nhà phát triển tiếp theo đang cố gắng tìm ra mã.


-1

Bạn có thể sử dụng envlệnh để đặt và hủy đặt các biến môi trường bằng hiphens "-".

Để thiết lập, bạn phải sử dụng env để chạy lệnh của mình : env command. Bạn chuyển các biến theo cách này:

env a-b=c command

Xem nó hoạt động với:

env a-b=c env

hoặc để làm cho nó rõ ràng hơn:

env a-b=c env|grep 'a-b'
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.