Sử dụng một tham chiếu biến trong bên trong một biến khác


27

Tôi chắc chắn rằng nó tương đối đơn giản, tôi chỉ không biết làm thế nào để làm điều đó.

#!/usr/bin/ksh
set `iostat`
myvar=6

Tôi muốn một cái gì đó echo ${$myvar}mà tôi muốn diễn giải là ${$myvar}-> ${6}->value


4
Thuật ngữ kỹ thuật là biến đổi hướng .
Thor

Câu trả lời:


29

Bạn có thể làm điều này với eval, tích hợp sẵn nhiều shell tốt, bao gồm ksh:

#!/usr/bin/ksh
set $(iostat)
myvar=6
eval "echo \${$myvar}"

Mẹo nhỏ là trích dẫn hai chuỗi mà bạn cung cấp để eval$ myvar được thay thế bằng "6" và gạch chéo ký hiệu đô la bên ngoài, để có evalđược chuỗi "$ 6".

Tôi đã nhận được "% user" cho đầu ra, nhưng tôi đã thử nó trên máy RHEL đa bộ xử lý.


3
Bạn chính thức là Đại sư tối cao của tuần b / c thậm chí hoạt động trên ksh khủng khiếp không thể tin được (thực sự là pdksh) trong OpenBSD 5.4. Nếu bạn muốn đặt var vv thành giá trị của var có tên trong var vn , chỉ cần làm vv=$( eval "echo \$$vn" ). Cảm ơn rất nhiều!
execNext

25

Tham chiếu biến gián tiếp

Các shell tiên tiến hiện đại có một phương thức để tham chiếu giá trị của một biến có tên được lưu trữ trong một biến khác. Thật không may, phương pháp này khác nhau giữa ksh, bash và zsh.

Trong mksh ≥R39b, bạn có thể tạo myvarmột nameref:

typeset -n myvar=6
echo "$myvar"

Điều này không hoạt động trong ATT ksh93 vì nó không hỗ trợ namerefs cho các tham số vị trí. Trong trường hợp bạn có một biến chứa tên biến, bạn có thể sử dụng phương thức này.

foo=bar
typeset -n myvar=foo
echo "$myvar"  # prints bar

Trong bash ≥2.0, bạn có thể viết

echo "${!myvar}"

Trong zsh, bạn có thể viết

echo ${(P)myvar}

Trong các shell cũ hơn, bao gồm ksh88 và pdksh, bạn chỉ cần truy vấn khi bạn có một biến chứa tên biến khác và muốn sử dụng giá trị của biến này eval, như Bruce Ediger giải thích . Giải pháp này hoạt động trong mọi vỏ Bourne / POSIX.

eval "value=\${$myvar}"
echo "$value"

Sử dụng một mảng

Đây là phương pháp tốt nhất ở đây: nó đơn giản và dễ mang theo hơn.

Đối với trường hợp sử dụng của bạn, trong bất kỳ shell nào có mảng (tất cả các biến thể ksh, bash ≥2.0, zsh), bạn có thể gán cho một biến mảng và lấy phần tử bạn muốn. Coi chừng các mảng ksh và bash bắt đầu đánh số 0, nhưng zsh bắt đầu từ 1 trừ khi bạn phát hành setopt ksh_arrayshoặc emulate ksh.

set -A iostat -- $(iostat)
echo "${iostat[5]}"

Nếu bạn muốn sao chép các tham số vị trí vào một biến mảng a:

set -A a -- "$@"

Trong ksh93, mksh R39b, bash 2.0 và zsh, bạn có thể sử dụng cú pháp gán mảng:

iostat=($(iostat))
echo "${iostat[5]}"

Ồ, giải pháp 'Bourne / POSIX' của bạn cũng hoạt động trong ksh / pdksh của OpenBSD 5.4. Để áp dụng nó vào ví dụ trong nhận xét của tôi cho câu trả lời của Bruce Ediger ở trên, chỉ cần làm eval "vv=\${$vn}". Merci beaucoup, loại thưa ngài.
execNext

1

Như được chỉ ra bởi Gilles (người đã cung cấp bashmột phần câu trả lời), cũng không làm mất hiệu lực của Bruce Ediger (về cách thực hiện một cách hợp lý eval), đây là cách thực hiện namereftrong gần đây mksh(và AT & T ksh93, ngoại trừ - như @Gilles đã nhận xét - namerefs không thể tham khảo các tham số vị trí trong AT & T ksh, chỉ tham số được đặt tên):

#!/bin/mksh
set -- $(iostat)
nameref myvar=6
echo $myvar

Thêm vào --sau setđể cải thiện sức đề kháng, quá.


Kể từ ksh 93u, namerefs không thể tham chiếu các tham số vị trí ( typeset: 6: invalid variable name).
Gilles 'SO- ngừng trở nên xấu xa'

0

Một cách sử dụng mảng khác

Không được sử dụng hoặc ksh hoặc bất kỳ biến thể nào trong một thời gian, vì vậy tôi không chắc chắn nếu ksh (hoặc bash) có khả năng tương tự. Vỏ chính của tôi là zsh. Tôi sử dụng mảng khi xử lý đầu ra từ các lệnh như iuler vì chúng tạo ra nhiều dòng và không phải tất cả các dòng đều có cùng định dạng / độ dài.

#! /bin/zsh
IOStatOutput=("${(@f)$(iostat)}") # Produces one element per line

Ở trên cũng bỏ qua việc sử dụng các tham số vị trí. Bây giờ, nếu bạn muốn tạo, giả sử, một loạt các thiết bị:

for Element in {7..${#IOStatOutput}} # Devices listed in elements 7 thru the last
do
    DevList+=( ${${=IOStatOutput[Element]}[1]} )
done

Tôi thấy khối nhỏ hơn dễ dàng hơn để xử lý. Bạn có thể hoặc không cần sử dụng tham chiếu biến gián tiếp, tùy thuộc vào mã của bạn. Biết làm thế nào nó hoạt động vẫn là một điều tốt để biết. Tôi sử dụng nó cho mình.

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.