30

我如何知道 bash 变量(空格分隔的标记)中的标记数量 - 或者至少,它是一个还是更多。

4

7 回答 7

39

$# 扩展将告诉您变量/数组中的元素数量。如果您使用的 bash 版本高于 2.05 左右,您可以:

VAR='some string with words'
VAR=( $VAR )
echo ${#VAR[@]}

这有效地将字符串沿空格(这是默认分隔符)拆分为一个数组,然后计算数组的成员。

编辑:

当然,这会将变量重新转换为数组。如果您不想这样,请使用不同的变量名或将变量重新转换为字符串:

VAR="${VAR[*]}"
于 2009-03-12T14:29:17.960 回答
33

我不明白为什么人们一直在使用那些过于复杂的 bashism。几乎总是有一个直截了当的、不拘泥的解决方案。

howmany() { echo $#; }
myvar="I am your var"
howmany $myvar

这使用了 shell 内置的标记器,因此没有差异。

这是一个相关的问题:

myvar='*'
echo $myvar
echo "$myvar"
set -f
echo $myvar
echo "$myvar"

请注意,@guns 使用 bash 数组的解决方案具有相同的问题。

以下是解决问题的(据说)超级强大的版本:

howmany() ( set -f; set -- $1; echo $# )

如果我们想避免使用 subshel​​l,事情就会变得丑陋

howmany() {
    case $- in *f*) set -- $1;; *) set -f; set -- $1; set +f;; esac
    echo $#
}

这两个必须使用 WITH 引号,例如howmany "one two three"返回3

于 2012-08-11T20:55:26.307 回答
14
set VAR='hello world'
echo $VAR | wc -w

这是您可以检查的方法。

if [ `echo $VAR | wc -w` -gt 1 ] 
then
    echo "Hello"
fi
于 2009-03-12T14:25:31.510 回答
1

简单方法:

$ VAR="a b c d"
$ set $VAR
$ echo $#
4
于 2009-03-12T14:27:49.990 回答
1

计算:

sentence="This is a sentence, please count the words in me."
words="${sentence//[^\ ]} "
echo ${#words}

去检查:

sentence1="Two words"
sentence2="One"
[[ "$sentence1" =~ [\ ] ]] && echo "sentence1 has more than one word"
[[ "$sentence2" =~ [\ ] ]] && echo "sentence2 has more than one word"
于 2011-11-03T23:37:10.843 回答
1

有关强大、可移植 sh的解决方案,请参阅@JoSo 的函数,使用set -f.

(用于回答(仅)“是否有至少 1 个空格?”问题的简单 bash-only 解决方案;注意:也将匹配前导和尾随空格,与awk下面的解决方案不同:

 [[ $v =~ [[:space:]] ]] && echo "\$v has at least 1 whitespace char."

)

这是一个基于健壮awk的 bash 解决方案(由于调用外部实用程序而效率较低,但在许多实际场景中可能无关紧要):

# Functions - pass in a quoted variable reference as the only argument.
# Takes advantage of `awk` splitting each input line into individual tokens by
# whitespace; `NF` represents the number of tokens.
# `-v RS=$'\3'` ensures that even multiline input is treated as a single input 
# string.
countTokens() { awk -v RS=$'\3' '{print NF}' <<<"$1"; }
hasMultipleTokens() { awk -v RS=$'\3' '{if(NF>1) ec=0; else ec=1; exit ec}' <<<"$1"; }

# Example: Note the use of glob `*` to demonstrate that it is not 
# accidentally expanded.
v='I am *'

echo "\$v has $(countTokens "$v") token(s)."

if hasMultipleTokens "$v"; then
  echo "\$v has multiple tokens."
else
  echo "\$v has just 1 token."
fi
于 2014-02-02T04:42:05.403 回答
-1

不确定这是否正是您的意思,但是:

$#= 传递给 bash 脚本的参数数量

否则你可能正在寻找类似的东西man wc

于 2009-03-12T14:23:59.190 回答