bash中的字符串长度


428

如何获取存储在变量中的字符串的长度并将其分配给另一个变量?

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

如何将另一个变量设置为输出11

Answers:


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').

Nota:根据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.shdiffU8test.sh.txt以了解更多限制。


我很欣赏这个答案,因为文件系统以字节而不是字符为单位强加了名称限制。
Gid

1
您可能还需要设置LC_ALL = C或其他。
伊莎贝尔·考恩

1
@ F.Hauri但是,仍然可以得出结论,在某些系统上,您的解决方案将不起作用,因为它只剩下LC_ALL。在Debian及其衍生版本的默认安装上,它可能工作正常,但在其他版本(如Arch Linux)上,它将无法给出字符串的正确字节长度。
伊莎贝尔·考恩

1
感谢您采取简单和令人费解的方法:)
thistleknot18年

2
@thistleknot对不起,对不起有时简单的只是一个想法。
F. Hauri '18

474

要获取存储在变量中的字符串的长度,请说:

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

要确认已正确保存,请执行以下操作echo

$ echo "$size"
11

8
使用UTF-8字符串,您可以具有字符串长度字节长度。看到我的答案
F. Hauri

您也可以直接在其他参数扩展中使用它-例如,在此测试中,我检查$rulename$RULE_PREFIX前缀是否为: [ "${rulename:0:${#RULE_PREFIX}}" == "$RULE_PREFIX" ]
Thomas Guyot-Sionnest

你能解释一下#myvarand 的表达{#myvar}吗?
Lerner

1
@lerneradams参见Bash参考手册→3.5.3 Shell Parameter Expansion on ${#parameter}替换参数扩展值的字符长度
fedorqui'SO停止伤害

25

您可以使用:

MYSTRING="abc123"
MYLENGTH=$(printf "%s" "$MYSTRING" | wc -c)
  • wc -cwc --bytes对于字节计数= Unicode字符以2、3或更多字节进行计数。
  • wc -mwc --chars字符计数= Unicode字符被单次计数,直到它们使用更多字节为止。


3
认真吗 一个微不足道的东西的管道,子shell和外部命令?
gniourf_gniourf '16

这会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}。第二个可能更本能,但语法不正确。


14
“您不能做<无效的语法>”的部分问题在于该语法无效,尚不清楚读者应该解释它的含义。size=${#1}当然是有效的。
Charles Duffy 2014年

好吧,这是出乎意料的。在这种情况下,我不知道#1可以代替$ 1。
Dick Guertin 2014年

16
不是。#并没有取代$- $外括号仍然是扩展操作符。该#是长度操作,一如既往。
查尔斯·达菲

我已经解决了这个问题,因为它是有用的提示,但不是该规则的例外-正如@CharlesDuffy所指出的,它完全遵循该规则
Zane Hooper

16

回应帖子的开始:

如果要在命令行或函数参数中使用它...

与代码:

size=${#1}

在某些情况下,您可能只想检查长度为零的参数而无需存储变量。我相信您可以使用以下语法:

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

GNU Bash条件表达式的更完整列表,和wooledge


11

使用提供的示例

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.