我试图列出具有特定前缀的所有变量,但该前缀是动态确定的。例如:
prefix=apple_
apple_one=a1
apple_two=a2
如果我简单地这样做:
echo ${!apple_@}
我可以获得以 apple_ 开头的变量名称。但是,我想通过某种方式使用变量前缀来做到这一点。我尝试过的一切都会导致糟糕的替代。例如我不能:
echo ${!${prefix}@}
答案1
Bash 不解析嵌套变量扩展。您可以执行您想要的操作eval
:构建 shell 代码片段${!apple_@}
,然后在执行的命令中使用它eval
。
prefix=apple_
eval 'vars=(${!'"$prefix"'@})'
确保prefix
仅包含有效的标识符字符,否则该片段可能会产生任何结果。
eval
通常需要使用动态计算名称的变量,但在这种特定情况下,有一种完全不同的方法可以完成同样的事情:使用完成系统。 Bash 的补全系统甚至可以通过脚本运行。内置函数compgen
每行列出一个补全,当补全可以包含换行符时,这是不明确的,但这里的情况并非如此——它们甚至不包含通配符,因此可以使用简单的不带引号的扩展来分割输出。如果前缀包含标识符中无效的字符,这将安全地不输出任何内容。
vars=($(compgen -v "$prefix"))
答案2
你可以使用env | grep '^prefix'
.
例如:
$ env | grep '^LESS'
LESSBINFMT=*u.
LESS=-MMqx4ij3
LESSOPEN=| /usr/bin/lesspipe %s
LESSCLOSE=/usr/bin/lesspipe %s %s
如果您只需要值而不需要变量名称,请使用 awk:
$ env | awk -F= '/^LESS/ {print $2}'
*u.
-MMqx4ij3
| /usr/bin/lesspipe %s
/usr/bin/lesspipe %s %s
(或仅打印 $1 作为变量名称)
更新2019-05-17
我通过赞成票回到了这个答案,并意识到有一个明显的改进:
typeset -p
比 效果更好env
,它输出所有变量,无论它们是否导出。例如:
typeset -p | awk '$3 ~ /^apple_/ { print $3 }'
要使用变量而不是固定字符串:
prefix=apple_
typeset -p | awk '$3 ~ "^"pfx { print $3 }' pfx="$prefix"
或者只是导出 $prefix 以便它可以在 awk 的 ENVIRON 数组中使用:
export prefix=apple_
typeset -p | awk '$3 ~ "^"ENVIRON["prefix"] { print $3 }'
笔记:只需做一点工作,就可以使其与其他 shell(例如 ksh 或 zsh)一起使用,但需要注意的是,typeset -p
其他 shell 的输出格式不同,因此必须修改 awk 脚本以适应它们。
答案3
preset(){
eval "printf %b $(#"
set -- "${1##[0-9]*}" _\[:alnum:]
[ -z "${1##*[!$2]*}" ]|| set |
sed -ne"s/^\($1[$2]*\)=.*/"'"${\1+\1\\n}" \\/p')
"; }; #"
apple_one="a single apple"
apple_two="an apple and an
apple_three='is not actually set at all'
"
preset apple_
apple_one
apple_two