Có thể sử dụng cảm ứng để thiết lập các biến?


7

Ví dụ tập lệnh tiếp theo sẽ in Hellodo ${!quy tắc.

A=B
B=Hello
echo ${!A}

Nhưng làm thế nào tôi có thể đặt giá trị thành biến với tên gián tiếp? Sử dụng !dấu hiệu đơn giản không hoạt động:

A=B
!A=Hello # here is tricky line
echo $B

Tôi biết có một mẹo khi sử dụng tệp tạm thời, nhưng tôi quan tâm đến việc sử dụng gián tiếp, không phải là một cái gì đó như

A=B
echo "$A=Hello" > 1.tmp
. 1.tmp
echo $B

2
eval $A=foobar
Forcefsck 18/03/13

Bạn có muốn tạo từ đồng nghĩa để cả hai biến đều trỏ đến cùng một dữ liệu không? Nói cách khác khi cái này thay đổi, cái kia thay đổi? Tôi không chắc tôi có ý định của bạn ở đây.
Christian

1
không, tôi chỉ muốn đặt một biến thông qua giá trị của một biến khác một lần
Sergey Grinev 18/03/13

Câu trả lời:


5

Một cách khác bạn có thể thử:

$ A=B
$ read $A <<< 81
$ echo "$B"
81

Nhưng có một rủi ro bảo mật (!) Như với tất cả các phương thức này (cũng declare/ typesetvà tất nhiên eval) .. Trong trường hợp này, người ta phải kiểm soát phía bên trái (giá trị của $A), nói cách khác, ít nhất là trong bash, biến $Akhông nên chứa đầu vào do người dùng kiểm soát, ví dụ: tệp đầu vào, vân vân ...


Nếu hệ vỏ của bạn không hỗ trợ chuỗi ở đây ( <<<), bạn cũng có thể sử dụng tài liệu ở đây:

A=B
read $A << EOF
82
EOF
echo "$B"

wow, nhưng tại sao nó hoạt động?
Serge Grinev 18/03/13

2
Shell mở rộng biến $ A trước lệnh đọc ..
Scrutinizer 18/03/13

Vấn đề duy nhất: nó không hoạt động trên Solaris
Sergey Grinev 18/03/13

1
Bạn có thể thử tài liệu ở đây thay vì chuỗi ở đây, xem phần chỉnh sửa trong bài đăng của tôi ..
Scrutinizer 18/03/13

2
Đây không phải là một phương pháp tốt. Nó phức tạp và sẽ phá vỡ nếu có các ký tự đặc biệt trong giá trị (dòng mới, dấu gạch chéo ngược và khoảng trắng ở đầu hoặc cuối trên một dòng có vấn đề).
Gilles 'SO- ngừng trở nên xấu xa'

11

Bạn có thể làm điều này với typesetnội dung:

$ A=B
$ typeset $A=42
$ echo $B
42

Hoặc sử dụng declare:

$ declare $A=1
$ echo $B
1

1
Trong bash, typesetlà lỗi thời và thay thế của nó là declare. Chúng giống nhau ít nhiều.
jw013

1
typesetlà một chút di động hơn mặc dù (hoạt động trong ksh)
Mat

cảm ơn! Không thể quyết định câu trả lời nào là tốt hơn. Lật một đồng xu :)
Serge Grinev 18/03/13

8

Tiếp theo gián tiếp khi nhận được giá trị của một biến ...

Cách di động là sử dụng eval. Bạn phải chú ý đến phần trích dẫn để các ký tự đặc biệt trong giá trị không được đánh giá khi chúng không nên. Cách dễ nhất là lưu trữ giá trị mới trong một biến trung gian và gán giá trị của biến đó.

A=B
tmp='stuff with special characters or whatever…'
eval $A=\$tmp

Đối số evalB=$tmp, một nhiệm vụ đơn giản. Bạn không cần dấu ngoặc kép xung quanh $tmpngay cả khi nó chứa các ký tự khoảng trắng hoặc toàn cầu, bởi vì chúng không được mở rộng trong một bài tập.

Nếu bạn muốn tạo một biến môi trường, bạn có thể sử dụng export. Trong bash hoặc ksh hoặc zsh, bạn có thể sử dụng typesetđể tạo biến cục bộ ( declaređồng nghĩa với bash). Một lần nữa, bạn nên sử dụng một biến trung gian để các ký tự đặc biệt không bị sai lệch. Lưu ý rằng ngoại trừ trong zsh, bạn cần đặt dấu ngoặc kép xung quanh việc mở rộng biến, bởi vì đây không phải là một phép gán mà là một nội dung có một đối số xảy ra giống như một phép gán.

export $A="$tmp"

Điều này (sử dụng eval) là câu trả lời chính xác. Nó di động, tuân thủ tiêu chuẩn POSIX và là tiêu chuẩn được sử dụng ở mọi nơi trong các tập lệnh shell nâng cao hơn. Mặc dù vậy, một điều: sử dụng exporttrên cùng một dòng với nhiệm vụ không phải là di động.
MadSellectist

@MadSellectist export var=valuelà POSIX. Nó không thể di chuyển được với vỏ Bourne, nhưng đây là một giống biến mất (chỉ cần đảm bảo sử dụng /usr/xpg4/bin/shhoặc /usr/xpg6/bin/shhoặc ksh chứ không phải /bin/shtrên các máy Solaris cũ).
Gilles 'SO- ngừng trở nên xấu xa'
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.