更新2019-05-17

更新2019-05-17

我试图列出具有特定前缀的所有变量,但该前缀是动态确定的。例如:

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

相关内容