tên biến bash động (biến)


12

Tôi muốn tự động tạo một chuỗi các chuỗi bằng cách thao tác một mảng các phần tử và tạo một số thủ tục số học.

for name in FIRST SECOND THIRD FOURTH FIFTH; do
    $name = $(( $6 + 1 ))
    $name = "${$name}q;d"
    echo "${$name}"; printf "\n"
done

Kết quả mong muốn sẽ là dưới đây cho $6bằng 0.

1q;d
2q;d
3q;d
4q;d
5q;d

Nhưng tôi gặp lỗi này

reel_first_part.sh: line 18: FIRST: command not found
reel_first_part.sh: line 19: ${$name}q;d: bad substitution
reel_first_part.sh: line 18: FIRST: command not found
reel_first_part.sh: line 19: ${$name}q;d: bad substitution
reel_first_part.sh: line 18: FIRST: command not found
reel_first_part.sh: line 19: ${$name}q;d: bad substitution

Tôi đoán đó là một cái gì đó đơn giản. Nó đã từng làm việc khi tôi làm một cái gì đó như

FIRST=$(( $6 + 1 ))
FIRST="${FIRST}q;d"

1
Bạn có thể giải thích nó tốt hơn một chút Đừng thực sự hiểu những gì bạn đang cố gắng làm.
nơ-ron

`$ Name = $ (($ 6 + 1))` phải làm gì?
PSkocik

@PSkocik Tôi đã hy vọng làm đượcFIRST=$(( $6 + 1 ))
gianni christofakis

Câu trả lời:


16

Trước hết không thể có bất kỳ khoảng trống nào =trong khai báo biến bash.

Để có được những gì bạn muốn bạn có thể sử dụng eval.

Ví dụ: tập lệnh mẫu như của bạn:

#!/bin/bash
i=0
for name in FIRST SECOND THIRD FOURTH FIFTH; do
    eval "$name"="'$(( $i + 1 ))q;d'"
    printf '%s\n' "${!name}"
    i=$(( $i + 1 ))
done

Bản in:

1q;d
2q;d
3q;d
4q;d
5q;d

Sử dụng evalthận trọng, một số người gọi nó là xấu xa vì một số lý do hợp lệ.

declare cũng sẽ làm việc:

#!/bin/bash
i=0
for name in FIRST SECOND THIRD FOURTH FIFTH; do
    declare "$name"="$(( $i + 1 ))q;d"
    printf '%s\n' "${!name}"
    i=$(( $i + 1 ))
done

cũng in:

1q;d
2q;d
3q;d
4q;d
5q;d

Là gì !dấu chấm than printf '%s\n' "${!name}"cho?
gianni christofakis

1
Nó được gọi là mở rộng gián tiếp mở rộng bashtham
số..đọc

1
Bash cũng có một thay thế đẹp hơn cho declare/ eval: printf -v varname '%fmt' args. Một số hàm nội bộ hoàn thành bash sử dụng hàm này để gọi theo tham chiếu. (truyền tên của một biến để lưu trữ vào).
Peter Cordes

Lưu ý: Sử dụng declarechỉ đặt biến trong phạm vi cục bộ, trong khi evalcách tiếp cận đặt biến trên toàn cầu.
người dùng

11

Nếu bạn muốn tham chiếu một biến bash trong khi có tên được lưu trữ trong một biến khác, bạn có thể làm như sau:

$ var1=hello
$ var2=var1
$ echo ${!var2}
hello

Bạn lưu trữ tên của biến bạn muốn truy cập, giả sử var2 trong trường hợp này. Sau đó, bạn truy cập vào nó với ${!<varable name>}nơi <variable name>là một biến giữ tên của biến bạn muốn truy cập.


Có cách cầm tay với eval var=\$$holdernhưng evalnguy hiểm!
gavenkoa

1
index=0;                                                                                                                                                                                                           
for name in FIRST SECOND THIRD FOURTH FIFTH; do
    name=$(($index + 1))
    echo "${name}q;d"
    index=$((index+1))
done

Có phải đó là những gì bạn đang cố gắng?


1

Những gì tôi nhận được từ mã của bạn và đầu ra mong muốn của bạn (sửa tôi nếu tôi sai):
Không sử dụng tên biến "FIRST" / "SECOND" / ..., bạn chỉ cần một vòng lặp với chỉ mục .. .

Điều này sẽ làm công việc:

for i in {1..5} ; do echo $i"q;d" ; done


Vâng, bạn đã đúng, ngoại trừ tôi muốn thực hiện một hàm số học với một biến.
gianni christofakis

Bạn có thể cho một ví dụ về hàm số học này? Bạn có cần tên biến (như "THIRD") cho nó hay chỉ giá trị chỉ mục?
csny

SUM=$(($6 + $i)); echo $SUM"q;d", Tôi thấy những gì tôi đã làm sai.
gianni christofakis
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.