Một cách tốt để làm việc evallà thay thế nó echođể thử nghiệm. echovà evalhoạt động tương tự (nếu chúng ta dành riêng phần \xmở rộng được thực hiện bởi một số echotriển khai như bashtrong một số điều kiện).
Cả hai lệnh tham gia đối số của chúng với một khoảng trắng ở giữa. Sự khác biệt là echo hiển thị kết quả trong khi eval đánh giá / diễn giải dưới dạng mã vỏ kết quả.
Vì vậy, để xem mã shell nào
eval $(echo $var_name=$var_value)
sẽ đánh giá, bạn có thể chạy:
$ echo $(echo $var_name=$var_value)
fruit=blue orange
Đó không phải là những gì bạn muốn, những gì bạn muốn là:
fruit=$var_value
Ngoài ra, sử dụng $(echo ...)ở đây không có ý nghĩa.
Để xuất ra ở trên, bạn sẽ chạy:
$ echo "$var_name=\$var_value"
fruit=$var_value
Vì vậy, để giải thích nó, đó chỉ đơn giản là:
eval "$var_name=\$var_value"
Lưu ý rằng nó cũng có thể được sử dụng để đặt các thành phần mảng riêng lẻ:
var_name='myarray[23]'
var_value='something'
eval "$var_name=\$var_value"
Như những người khác đã nói, nếu bạn không quan tâm mã của mình là bashcụ thể, bạn có thể sử dụng declarenhư:
declare "$var_name=$var_value"
Tuy nhiên lưu ý rằng nó có một số tác dụng phụ.
Nó giới hạn phạm vi của biến đối với chức năng nơi nó chạy. Vì vậy, bạn không thể sử dụng nó trong ví dụ như:
setvar() {
var_name=$1 var_value=$2
declare "$var_name=$var_value"
}
setvar foo bar
Bởi vì điều đó sẽ khai báo một foobiến cục bộ để setvarnhư vậy sẽ vô dụng.
bash-4.2đã thêm một -gtùy chọn declaređể khai báo một biến toàn cục, nhưng đó không phải là điều chúng ta muốn vì chúng ta setvarsẽ đặt một biến toàn cục trái ngược với biến của người gọi nếu người gọi là một hàm, như trong:
setvar() {
var_name=$1 var_value=$2
declare -g "$var_name=$var_value"
}
foo() {
local myvar
setvar myvar 'some value'
echo "1: $myvar"
}
foo
echo "2: $myvar"
mà sẽ xuất ra:
1:
2: some value
Ngoài ra, lưu ý rằng trong khi declaređược gọi declare(thực tế đã bashmượn khái niệm từ typesetnội dung của vỏ Korn ), nếu biến đã được đặt, declaresẽ không khai báo một biến mới và cách thực hiện chuyển nhượng phụ thuộc vào loại biến.
Ví dụ:
varname=foo
varvalue='([PATH=1000]=something)'
declare "$varname=$varvalue"
sẽ tạo ra một kết quả khác (và có khả năng có tác dụng phụ khó chịu) nếu varnametrước đây được khai báo là mảng vô hướng , mảng hoặc mảng kết hợp .
evalcách đó là sai. Bạn đang mở rộng$var_valuetrước khi chuyển nó sangevalđiều đó có nghĩa là nó sẽ được hiểu là mã shell! (thử ví dụ vớivar_value="';:(){ :|:&};:'")