bash変数内のトークン(空白で区切られたトークン)の数を知るにはどうすればよいですか?少なくとも、それが1つであるか複数あるかを知ることができます。
$#展開は、変数/配列内の要素の数を示します。 2.05以上のbashバージョンを使用している場合は、次のことができます。
VAR='some string with words'
VAR=( $VAR )
echo ${#VAR[@]}
これにより、文字列が空白(デフォルトの区切り文字)に沿って配列に効果的に分割され、配列のメンバーがカウントされます。
編集:
もちろん、これは変数を配列として再キャストします。それが望ましくない場合は、別の変数名を使用するか、変数を文字列に再キャストします。
VAR="${VAR[*]}"
なぜ人々がこれらの過度に複雑なバシズムをいつも使っているのか理解できません。ほとんどの場合、簡単で恥ずかしくない解決策があります。
howmany() { echo $#; }
myvar="I am your var"
howmany $myvar
これはシェルに組み込まれているトークナイザーを使用するため、矛盾はありません。
関連する落とし穴が1つあります。
myvar='*'
echo $myvar
echo "$myvar"
set -f
echo $myvar
echo "$myvar"
Bash配列を使用した@gunsのソリューションにも同じ落とし穴があることに注意してください。
以下は、落とし穴を回避するための(おそらく)超堅牢なバージョンです。
howmany() ( set -f; set -- $1; echo $# )
サブシェルを避けたい場合、物事は醜くなり始めます
howmany() {
case $- in *f*) set -- $1;; *) set -f; set -- $1; set +f;; esac
echo $#
}
これらの2つは、引用符で囲む必要があります。 howmany "one two three"
戻り値 3
set VAR='hello world'
echo $VAR | wc -w
確認方法は次のとおりです。
if [ `echo $VAR | wc -w` -gt 1 ]
then
echo "Hello"
fi
カウントする:
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"
堅牢なportablesh
ソリューションについては、 @ JoSoの関数 using set -f
。
(「少なくとも1つの空白がありますか?」という質問に(のみ)答えるための単純なbashのみのソリューション。注:以下の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
簡単な方法:
$ VAR="a b c d"
$ set $VAR
$ echo $#
4