要测试变量是否为只读,有以下丑陋的技巧:
# True if readonly
readonly -p | egrep "declare -[:lower:]+ ${var}="
# False if readonly
temp="$var"; eval $var=x 2>/dev/null && eval $var=\$temp
有没有更优雅的解决方案?
要测试变量是否为只读,有以下丑陋的技巧:
# True if readonly
readonly -p | egrep "declare -[:lower:]+ ${var}="
# False if readonly
temp="$var"; eval $var=x 2>/dev/null && eval $var=\$temp
使用子Shell 似乎是可以的。无论是使用本地变量还是导出变量都可以。
$ foo=123
$ bar=456
$ readonly foo
$ echo $foo $bar
123 456
$ (unset foo 2> /dev/null) || echo "Read only"
Read only
$ (unset bar 2> /dev/null) || echo "Read only"
$
$ echo $foo $bar
123 456 # Still intact :-)
已在bash和ksh中进行测试。
您还可以向变量添加一个空字符串,这仍然会保留它的值,但比使用子shell更快,例如:
foo+= 2>/dev/null || echo "Read only"
is-writable() { eval "$1+=" >2/dev/null; }
foo
未设置,此测试将将其设置为空字符串,因此您也需要对其进行测试。 - Logoleptfoo
未设置并且还具有nameref属性,则即使foo
不是只读的,测试也会失败,因为空字符串不是有效的变量名。 - Logoleptis-writable 'rm -rf / #'
"(不要运行!)而导致的危险:在函数中使用本地 nameref 变量而不是 eval。当然,如果您恰好使用了一个之前设置为只读的本地变量,它将破坏您的函数。 - Logolept
[ -R varname ]
或readonly -t varname
(其中t
表示测试)来测试这个问题将会很优雅。 - l0b0