要检查 $i 是否等于任何命令行参数(在 Bash 脚本中),我使用
if [[ " $@ " =~ " $i " ]]
有没有更好的办法?
我的意思是,一种更值得推荐、更通用等但几乎同样简单的方法。
如果我是正确的,当 $i 和每个命令行参数不包含空格时,上面的方法有效。在大多数情况下这很好,但也许有一个简单的修复方法或其他一些简单的改进。
在这种特殊情况下,我认为 $* 同样有效,但一般来说更值得推荐吗?他们的区别可以在这里找到:https://stackoverflow.com/questions/3898665/what-is-in-bash
答案1
如果可以选择切换到zsh
,那么它应该是:
set 'foo bar' 1:2 $'a\nb'
i='foo bar'
if (( n = $argv[(Ie)$i] )); then
print -r -- "$i is found among the positional parameters, in \${$n} at least"
fi
在 中zsh
,位置参数也可以在数组中使用,$argv
就像在 csh 中一样。数组I
下标标志导致下标被视为模式,并且扩展返回I
其值与模式匹配的最后一个元素的索引(如果未找到,则返回 0)。用于xact 匹配e
而e
不是模式匹配。在这里,我们将结果分配给n
ksh 样式的算术表达式(如果表达式像往常一样解析为非零值,则返回 true)。
在 中zsh
,还可以构造一个$@
与 with 的任何元素匹配的模式:
pattern="(${(j[|])${(b)@}})"
在那里,b
参数扩展标志转义 glob,j[|]
将结果元素与 结合起来|
,因此您最终会得到一个(foo|bar|\*|)
模式 afterset -- foo bar '*' ''
例如。
用作:
if [[ $i = $~pattern ]]...
但请注意,如果位置参数列表为空,则将以()
与空字符串错误匹配的模式结尾。
如果最终目的是查找数组的哪些元素也在位置参数中找到,则可以使用 zsh 的数组交集运算符:${A:*B}
。
set a A 'x y'
array=(a b 'x y' a)
print -r Found in argv: ${array:*argv}
$i
在 bash 或任何 POSIX shell 中,如果您知道某个字符或任何位置参数中没有出现,您可以执行以下操作:
IFS=: # join "$*" with :
case ":${*}:" in
(*:"$i":*) printf '%s\n' "$i is among the positional parameters";;
esac
与您的方法类似,只是它使用标准 sh 语法而不是[[ ... ]]
kshism 和不可移植的(甚至跨 bash 版本)=~
(与bash 中更=~
简单的相比,也会在非文本字符串上阻塞),这里我们将分隔符修复为与任意的空间不同,您需要知道哪个最不可能出现在您的用例中或位置参数中。在列表上下文之外使用也没有什么意义,并且不同 shell 的行为也不同。在非列表上下文中有意义,其中明确指定将位置参数与 的第一个字符连接。=
:
$i
"$@"
"$*"
$IFS
您可以使用 ksh 样式[[ ... ]]
代替case
:
if [[ ":${*}:" = *:"$i":* ]]...
为了能够使用任意值,bash
您必须使用循环:
found=false
for arg do
if [ "$arg" = "$i" ]; then
found=true
break
fi
done
if "$found"; then
printf '%s\n' "$i is among the positional parameters"
fi
您还可以定义一个辅助函数:
among() {
local needle="$1" arg
shift
for arg do
[ "$arg" = "$needle" ] && return
done
false
}
if among "$i" "$@"; then
printf '%s\n' "$i is among the positional parameters"
fi
答案2
要检查是否
$i
等于任何命令行参数(在 Bash 脚本中),我使用if [[ " $@ " =~ " $i " ]]
最好的情况是查看命令行是否包含的价值$i
。例如,如果您有i=the
命令行参数之一,则the elephant
条件将匹配。
但是,您还使用了$@
which,当在双引号内使用时,通常会扩展为一系列带引号的参数单词。在这里我希望您使用"$*"
. (使用bash
做[[ … ]]
正确的事情并用作$@
单个字符串,但这并不意味着使用 是正确的$@
。)
最好是这样,但它仍然受到包含而不是等于:
if [[ " $* " =~ " $i " ]]
检查是否$i
等于我认为您必须遍历该集合的任何命令行参数:
success=false
for arg in "$@"; do [[ "$arg" = "$i" ]] && { success=true; break; }; done
if "$success"
这可以更优雅地表达为另一个答案作为函数among
.