测试变量是否为只读

问题描述 投票:0回答:3

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

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

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

有更优雅的解决方案吗?

bash
3个回答
11
投票

使用子 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 也可以挽救您的 RW(在本例中为 $bar),使其免于在当前 shell 中被取消设置。

使用 bash 和 ksh 进行测试。


2
投票

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

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

捕获为函数,它将是:

is-writable() { eval "$1+=" >2/dev/null; }

0
投票

在问题中,

readonly
的输出被解析为变量名称。类似的方法(避免使用 eval 或 egrep)是检查
declare -p <VARNAME>
是否包含只读标志(或任何其他与此相关的属性)。

# @usage: is_var [-Aailnrtux] <VARNAME>
is_var(){
  local i n f=""; [ "${1:0:1}" == - ] && { f="${1:1}"; n=${#f}; shift; }
  [[ "$1" =~ ^[_[:alpha:]][_[:alpha:][:digit:]]*$ ]] || return 1
  declare -a v && read -ra v < <( declare -p "$1" 2>/dev/null )
  [ ${#v} == 0 ] && return 2
  [ "$f" ] || return 0
  for ((i=0;i<n;++i)) do [[ "${v[1]}" = *"${f:i:1}"* ]] || return 3; done
}
is_array(){ is_var -a "$1"; return $?; };
is_readonly(){ is_var -r "$1"; return $?; };

# examples
is_var HOME && echo "HOME is $HOME"
is_var "foo bar" || echo baz
is_readonly PPID && echo "$_ is readonly" || echo "$_ can be (un)set"
is_array BASH_ARGC && echo "$_ is an array" || echo "$_ is no array"
© www.soinside.com 2019 - 2024. All rights reserved.