例如,如果我构建一个数组:
$ array1=($(find /etc -mindepth 1 -maxdepth 1 -type d))
$ echo ${#array[@]}
105
$ for each in ${array1[@]}; do echo $each ; done
/etc/alternatives
/etc/apache2
/etc/apparmor
/etc/apparmor.d
... so on and so forth, you get the idea.
有没有办法使用 bash 打印字节大小,而不是长度?或者我只需要根据字符数手动进行数学计算?
我尝试过这样的事情:
$ var2="a"
$ echo $var2 | wc -c
2
$ echo $var2
a
但接下来这个:
$ var2=""
$ echo $var2 | wc -c
1
$ echo $var2
似乎空白变量的存在是1个字节。但 1 个字母的字符数也是 2 个字符。
$ echo a | wc -c
2
$ echo a | wc -m
2
$ echo aa | wc -c
3
$ echo aa | wc -m
3
看起来换行是一个字节,每个字符也是一个字节。获取一个数组,计算新行数,计算字符数,然后进行数学计算似乎很困难。我是否想得太多了,或者是否有一个实用程序可以给我一个准确的数字?
答案1
array1=($(find /etc -mindepth 1 -maxdepth 1 -type d))
这是错误的,因为它对 的输出执行 split+glob 来find
获取列表(并且find
without的输出-print0
无论如何都不可进行后处理)。 (4.4+)中正确的语法bash
是:
readarray -td '' array1 < <(find /etc -mindepth 1 -maxdepth 1 -type d -print0)
或者在zsh
:
array1=(/etc/*(ND/))
在echo $var | wc -c
您正在计算 输出中的字节数echo
。$var
由于以下几个原因,这不是字节数:
- 你忘了引用,
$var
所以它受到 split+glob 的影响 echo
进行一些转换。有些实现扩展\x
转义序列,有些将值视为-n
选项- 最后,
echo
在输出中附加一个换行符(-n
在某些实现中可以跳过它echo
)。
在这里,要用来wc
计算字节数,您可以这样做:
printf %s "$var" | wc -c
在 中bash
,${#var}
扩展到人物在变量中。为了使其成为字节数,您可以将语言环境固定为 C:
LC_ALL=C
echo "${#var}"
要获取数组所有元素的字节长度总和,可以将它们连接起来,然后获取结果字符串的长度:
printf %s "${array[@]}" | wc -c
或者:
IFS=
concat="${array[*]}"
LC_ALL=C
echo "${#concat}"
使用 zsh,你可以这样做:
() { set -o localoptions +o multibyte
echo ${#${(j[])array}}
}
其中j[sep]
参数扩展标志用于连接数组的元素,而不是使用"${array[*]}"
which 使用全局$IFS
.C
我们可以禁用该multibyte
选项来获取,而不是修复区域设置特点≍字节(我们在本地匿名函数中执行此操作)。
请注意,要查看字节和字符之间的差异,您需要一种使用多字节编码作为其字符映射(例如 UTF-8、GB18030、BIG5...)的语言环境以及在多个字节上编码的字符。a
通常以一个字节进行编码,因此您不会看到差异。€
例如,在 UTF-8 中编码为 3 个字节,在 ISO8859-15 中编码为 1 个字节。
一个例子(来自zsh
):
$ a=($'\xe2\x82\xac20' '$25' $'\xa420')
$ locale charmap
UTF-8
$ typeset -p a
typeset -a a=( €20 '$25' $'\M-$20' )
$ printf %s "${a[@]}" | wc -c
11
$ printf %s "${a[@]}" | wc -m
8
$ echo ${#${(j[])a}}
9
$ (){set -o localoptions +o multibyte; echo ${#${(j[])a}}}
11
如果我切换到字符映射为 ISO8859-15 的区域设置:
$ locale charmap
ISO-8859-15
$ a=($'\xe2\x82\xac20' '$25' $'\xa420')
$ typeset -p a
typeset -a a=( â¬20 '$25' €20 )
$ printf %s "${a[@]}" | wc -c
11
$ printf %s "${a[@]}" | wc -m
11
$ echo ${#${(j[])a}}
11
$ (){set -o localoptions +o multibyte; echo ${#${(j[])a}}}
11
ISO8859-15是单字节字符编码,所以特点≍字节那里。
更多阅读:
与 bash(或 zsh)类似wc -m
,但 bash(或 zsh)也会将无法解码为字符的字节分别计算为一个字符。