bashの文字列の長さ


428

変数に格納されている文字列の長さを取得して別の変数に割り当てるにはどうすればよいですか?

myvar="some string"
echo ${#myvar}  
# 11

別の変数を出力にどのように設定します11か?

回答:


270

UTF-8文字列の長さ

fedorquiの正解に加えて、文字列の長さとバイトの長さの違いを示したいと思います。

myvar='Généralités'
chrlen=${#myvar}
oLang=$LANG oLcAll=$LC_ALL
LANG=C LC_ALL=C
bytlen=${#myvar}
LANG=$oLang LC_ALL=$oLcAll
printf "%s is %d char len, but %d bytes len.\n" "${myvar}" $chrlen $bytlen

レンダリングされます:

Généralités is 11 char len, but 14 bytes len.

格納されている文字を確認することもできます。

myvar='Généralités'
chrlen=${#myvar}
oLang=$LANG oLcAll=$LC_ALL
LANG=C LC_ALL=C
bytlen=${#myvar}
printf -v myreal "%q" "$myvar"
LANG=$oLang LC_ALL=$oLcAll
printf "%s has %d chars, %d bytes: (%s).\n" "${myvar}" $chrlen $bytlen "$myreal"

答えます:

Généralités has 11 chars, 14 bytes: ($'G\303\251n\303\251ralit\303\251s').

注意:Isabell Cowanのコメントによると、にの設定を追加$LC_ALLしました$LANG

引数の長さ

引数は通常の変数と同じように機能します

strLen() {
    local bytlen sreal oLang=$LANG oLcAll=$LC_ALL
    LANG=C LC_ALL=C
    bytlen=${#1}
    printf -v sreal %q "$1"
    LANG=$oLang LC_ALL=$oLcAll
    printf "String '%s' is %d bytes, but %d chars len: %s.\n" "$1" $bytlen ${#1} "$sreal"
}

として機能します

strLen théorème
String 'théorème' is 10 bytes, but 8 chars len: $'th\303\251or\303\250me'

便利なprintf修正ツール:

もし、あんたが:

for string in Généralités Language Théorème Février  "Left: ←" "Yin Yang ☯";do
    printf " - %-14s is %2d char length\n" "'$string'"  ${#string}
done

 - 'Généralités' is 11 char length
 - 'Language'     is  8 char length
 - 'Théorème'   is  8 char length
 - 'Février'     is  7 char length
 - 'Left: ←'    is  7 char length
 - 'Yin Yang ☯' is 10 char length

本当にきれいではありません...このために、小さな関数があります:

strU8DiffLen () { 
    local bytlen oLang=$LANG oLcAll=$LC_ALL
    LANG=C LC_ALL=C
    bytlen=${#1}
    LANG=$oLang LC_ALL=$oLcAll
    return $(( bytlen - ${#1} ))
}

そして今:

for string in Généralités Language Théorème Février  "Left: ←" "Yin Yang ☯";do
    strU8DiffLen "$string"
    printf " - %-$((14+$?))s is %2d chars length, but uses %2d bytes\n" \
        "'$string'" ${#string} $((${#string}+$?))
  done 

 - 'Généralités'  is 11 chars length, but uses 14 bytes
 - 'Language'     is  8 chars length, but uses  8 bytes
 - 'Théorème'     is  8 chars length, but uses 10 bytes
 - 'Février'      is  7 chars length, but uses  8 bytes
 - 'Left: ←'      is  7 chars length, but uses  9 bytes
 - 'Yin Yang ☯'   is 10 chars length, but uses 12 bytes

残念ながら、これは完璧ではありません!

しかし、ダブルスペース文字、ゼロスペース文字、逆置換など、それほど単純ではない可能性がある奇妙なUTF-8動作が残っていました...

その他の制限については、diffU8test.shまたはdiffU8test.sh.txtをご覧ください。


ファイルシステムでは名前に文字数ではなくバイト数の制限があるため、この回答に感謝します。
2016年

1
LC_ALL = Cおよびおそらく他の設定も必要になる場合があります。
Isabell Cowan 2016

1
@ F.Hauriしかし、一部のシステムではLC_ALLがそのままになっているため、ソリューションが機能しないことは変わりません。Debianのデフォルトインストールとその派生物では問題なく動作する可能性がありますが、他のデバイス(Arch Linuxなど)では、文字列の正しいバイト長を提供できません。
Isabell Cowan 2017

1
単純なものを取って複雑にしてくれてありがとう:)
thistleknot

2
@thistleknot申し訳ありませんが、不不起時々シンプルなのは単なるアイデアです。
F. Hauri

474

変数に格納されている文字列の長さを取得するには、次のようにします。

myvar="some string"
size=${#myvar} 

適切に保存されたことを確認するには、次のechoようにします。

$ echo "$size"
11

8
UTF-8文字列を使用すると、文字列の長さバイトの長さ持つことができます。私の回答を参照してください
F.ハウリ

また、他のパラメータ展開でそれを直接使用することができます-例えば、このテストでは、私はそれをチェック$rulenameして開始を$RULE_PREFIX接頭辞: [ "${rulename:0:${#RULE_PREFIX}}" == "$RULE_PREFIX" ]
トーマス・ギヨー-Sionnest

#myvarand の表現について少し説明してもらえます{#myvar}か?
Lerner Zhang

1
@lerneradamsは、参照→3.5.3シェルパラメータ拡張バッシュリファレンスマニュアル${#parameter}パラメータの拡張値の文字の長さが置換されます
fedorqui「SO害をやめる」

25

以下を使用できます。

MYSTRING="abc123"
MYLENGTH=$(printf "%s" "$MYSTRING" | wc -c)
  • wc -cまたはwc --bytesバイトカウントの場合= Unicode文字は2、3、またはそれ以上のバイトでカウントされます。
  • wc -mまたはwc --chars文字数の場合=より多くのバイトを使用するまで、Unicode文字は1つとしてカウントされます。


3
マジ?ささいなことのためのパイプ、サブシェル、および外部コマンド?
gniourf_gniourf 2016

これは次のようなものを処理しますmylen=$(printf "%s" "$HOME/.ssh" | wc -c)が、受け入れられたソリューションは失敗し、myvar=$HOME/.ssh最初に行う必要があります。
JL Peyret

23

私は最も単純なケースが欲しかった、最後にこれは結果です:

echo -n 'Tell me the length of this sentence.' | wc -m;
36

4
ごめんなさい:(これはbashです...すべてを釘、特に親指と見なす呪われたハンマーです。「この文章の長さを教えてください」は36文字です。 echo '' | wc -m=> 1。使用する必要があります-necho -n '' | wc -m=> 0...その場合、それは良い解決策です:)
AJP

1
訂正ありがとうございます!マニュアルページは言う: -n do not output the trailing newline
dmatej

17

コマンドラインまたは関数の引数でこれを使用する場合は、のsize=${#1}代わりに使用してくださいsize=${#$1}。2つ目はより本能的かもしれませんが、構文が正しくありません。


14
「<無効な構文>を実行することはできません」の問題の一部は、その構文が無効であるため、読者がそれをどのように解釈すべきかが明確でないことです。size=${#1}確かに有効です。
Charles Duffy

まあ、それは予想外です。この場合、#1が$ 1の代わりになることを知りませんでした。
ディックガーティン2014年

16
そうではありません。#を置き換えていません$- $中括弧の外側はまだ拡張演算子です。#いつものように、長さ演算子です。
Charles Duffy、2014年

それは@CharlesDuffyで尖ったアウトとして、正確にルールに従います-それは便利な先端ではなく、規則の例外ですので、私はこの答えを修正しました
ゼイン・フーパー

16

投稿の開始に応じて:

コマンドラインまたは関数の引数でこれを使用したい場合...

コードで:

size=${#1}

長さゼロの引数をチェックするだけで、変数を格納する必要がない場合があります。このような構文を使用できると思います。

if [ -z "$1" ]; then
    #zero length argument 
else
    #non-zero length
fi

Bashの条件式のより完全なリストについては、GNUwooledgeを参照してください。


11

提供された例を使用する

#KISS (Keep it simple stupid)
size=${#myvar}
echo $size

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.