我仅限于 Bash。
我想回显两个字符串之一,具体取决于是否设置了参数。
比方说
if $ARG is notset|empty then print X
if $ARG is set&nonempty then print V
我对 $ARG 内容完全不感兴趣。无论是否提供和填写。
我知道我可以通过 IF/CASE/等得到这个结果。但我会多次使用这个结构,并且我想保持简洁。我知道我可以用任何方式做到这一点并将其包装到一个函数中,但我很好奇是否可以用某种智能方式(即参数扩展)来制作它?
我已读完https://tldp.org/LDP/abs/html/parameter-substitution.html和一些类似的页面,我注意到有两个类似的、看似互补的操作:
default value: ${ARG:-X}
alternative value: ${ARG:+V}
顺便说一下,这就是问题标题的来源。:-
空时返回 X,:+
非空时返回 V。
一个简单的:
echo ${ARG:+V}${ARG:-X}
做几乎我想要的是。X
当$ARG
为空或未设置时打印出,但在任何其他情况下,例如 ARG=foo,它都会打印出Vfoo
。那是因为:+
和:-
并不是我想要的真正互补的方式;)为了让它像简单的串联一样工作,${}${}
我需要一个“逆”,:+
当空时输出“默认”,或者不输出任何内容(不是:测试的变量)。
似乎我需要一些像这样的怪物复合命令${ARG:+V:-X}
(它不起作用,因为它与 alt_value:+
一起使用V:-X
),它一次性执行此操作,根据参数的状态在两个给定值之间进行选择,并且不真正使用参数保存的实际文本。
我天真地尝试过嵌套
echo ${${ARG:+V}:-X}
这正是我所需要的,但它在 Bash 中不起作用,因为它是范围扩展,并且内部${ARG:+V}
不是参数,因此外部${}
会抱怨。 (~命令替换可以嵌套在变量替换中吗?)
Vfoo
我想我可以尝试通过将其减少到第一个字符来修复${xxx:0:1}
,但是,这将需要再次嵌套${${ARG:+V}${ARG:-X}:0:1}
,所以不行。
或者一个辅助变量,在这种情况下就可以了:
MINGW64 ~
$ f () { T=${1:+V}${1:-X} ; echo ${T:0:1} ; } ;
$ f "a"
V
$ f ""
X
$ f
X
这是我能得到的最接近的结果,甚至有我想要的行为。
感觉有点脏,因为它实际上构造任意长的字符串T
只是为了获取它的第一个字符。纯粹浪费。
另外,我仍然想将它压缩成一个表达式,而不需要临时变量T
。
我错过了 Bash 中的某些内容吗?我可以通过参数扩展或任何其他内置技巧以更好的方式获得这种“选择”行为吗?
答案1
你可以这样做:
either=(
'value for unset or empty'
'value for set and non-empty'
)
printf '%s\n' "${either[!!${#VAR}]}"
set +o histexpand
(如果尝试通过交互式 bash 调用,请禁用历史扩展 ( ))。
${#VAR}
扩展为 , 值中的字符数$VAR
,!!
是双重否定,!!${#VAR}
因为如果变量为空或未设置,则算术表达式生成 0,否则生成 1。
使用zsh
,您可以执行以下操作:
print -r -- ${${var:+value for set and non-empty}:-value for unset or empty}