bash: 如果 $i 等于任何命令行参数: if [[ " $@ " =~ " $i " ]]

bash: 如果 $i 等于任何命令行参数: if [[ " $@ " =~ " $i " ]]

要检查 $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 匹配ee不是模式匹配。在这里,我们将结果分配给nksh 样式的算术表达式(如果表达式像往常一样解析为非零值,则返回 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.

相关内容