测试变量是否为只读

5

要测试变量是否为只读,有以下丑陋的技巧:

# True if readonly
readonly -p | egrep "declare -[:lower:]+ ${var}="

# False if readonly
temp="$var"; eval $var=x 2>/dev/null && eval $var=\$temp

有没有更优雅的解决方案?

你为什么认为这很重要? - Ignacio Vazquez-Abrams
询问某事并不意味着它很重要。在其他地方,优雅与重要并没有关联。 - enguerran
只有在你关心脚本的可读性时才显得重要。例如,能够使用[ -R varname ]readonly -t varname(其中t表示测试)来测试这个问题将会很优雅。 - l0b0
2个回答

10

使用子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 :-)

重要的是,即使是子shell,在当前shell中也可以恢复你的RW(在这种情况下为$bar),以避免其未设置。

已在bash和ksh中进行测试。


3

您还可以向变量添加一个空字符串,这仍然会保留它的值,但比使用子shell更快,例如:

foo+= 2>/dev/null || echo "Read only"

以函数形式捕获,代码如下:
is-writable() { eval "$1+=" >2/dev/null; }

1
如果foo未设置,此测试将将其设置为空字符串,因此您也需要对其进行测试。 - Logolept
在现代的Bash中,如果foo未设置并且还具有nameref属性,则即使foo不是只读的,测试也会失败,因为空字符串不是有效的变量名。 - Logolept
另一方面,bash 会帮助您避免因意外或故意写入类似 "is-writable 'rm -rf / #'"(不要运行!)而导致的危险:在函数中使用本地 nameref 变量而不是 eval。当然,如果您恰好使用了一个之前设置为只读的本地变量,它将破坏您的函数。 - Logolept

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接