Thay thế $ {! Var_name + x} có nghĩa là gì?


10

Tôi đã tìm thấy một tập lệnh có chức năng kiểm tra nếu một biến được đặt nhưng tôi không hiểu rõ về nó.

check_if_variable_is_set() {
    var_name=$1
    if [ -z "${!var_name+x}" ]; then
        false
    else
        true
    fi
}

Điều gì chính xác xảy ra với sự thay thế này?


Câu trả lời:


17

Trong bashvỏ, ${!var}là một biến đổi không định hướng. Nó mở rộng đến giá trị của biến có tên được giữ trong đó $var.

Mở rộng biến ${var+value}một mở rộng POSIX mở rộng đến valuenếu biến varđược đặt (bất kể giá trị của nó có trống hay không).

Kết hợp những thứ này, ${!var+x}sẽ mở rộng thành xnếu biến có tên được giữ trong đó $varđược đặt.

Thí dụ:

$ foo=hello
$ var=foo
$ echo "${!var+$var is set, its value is ${!var}}"
foo is set, its value is hello
$ unset foo
$ echo "${!var+$var is set, its value is ${!var}}"

(dòng trống là đầu ra)


Hàm trong câu hỏi có thể rút ngắn thành

check_if_variable_is_set () { [ -n "${!1+x}" ]; }

hoặc thậm chí:

check_if_variable_is_set () { [ -v "$1" ]; }

hoặc thậm chí:

check_if_variable_is_set()[[ -v $1 ]]

Trong trường hợp -vlà một bashthử nghiệm trên một tên biến mà sẽ là true nếu biến có tên được thiết lập, và sai khác.


POSIXly, nó có thể được viết:

check_if_variable_is_set() { eval '[ -n "${'"$1"'+x}" ]'; }

Lưu ý rằng tất cả chúng là các lỗ hổng tiêm lệnh tiềm năng nếu đối số của hàm đó có thể bị kiểm soát bởi kẻ tấn công. Hãy thử ví dụ với check_if_variable_is_set 'a[$(id>&2)]'.

Để bảo vệ chống lại điều đó, trước tiên bạn có thể muốn xác minh rằng đối số là tên biến hợp lệ. Đối với các biến:

check_if_variable_is_set() {
  case $1 in
    ("" | *[![:alnum:]_]* | [![:alpha:]_]*) false;;
    (*)  eval '[ -n "${'"$1"'+x}" ]'
  esac
}

(lưu ý rằng [[:alpha:]]sẽ kiểm tra các ký tự chữ cái trong ngôn ngữ của bạn trong khi một số shell chỉ chấp nhận các ký tự chữ cái từ bộ ký tự di động trong biến của chúng)


Không có gì trên trái đất đầy đủ hơn thế này. Bạn xứng đáng với một cookie cho điều đó.
Karim Manaouil

@KarimManaouil Một phần ba của cookie đó đến Stéphane mặc dù :-)
Kusalananda
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.