我有一个读取输入并计算字符出现次数的脚本。它基于数组:
parse_stream () {
while read -n 1 char; do
if [[ -n $char ]]; then
((count++))
((chars[\\$char]++))
fi
done
}
它打印一个读取数组的简单报告:
print_results () {
{ for i in "${!chars[@]}"; do
echo -e "$i" "\t" ${chars["$i"]}
done } | sort
}
我得到的结果保持字母顺序,但混合了小写和大写字母:
0 3362
[ 1
/ 1213
: 1628
_ 168
1 7282
* 2337
2 3922
+ 24
3 2261
4 2042
. 508
5 1624
> 575
6 1879
- 7128
7 1345
8 1895
9 853
A 1
a 2610
b 578
c 1430
C 2
D 1
d 1179
E 2
e 3166
F 1
f 853
G 1
g 962
H 1
h 633
I 11
i 2955
j 254
k 1157
l 2619
M 13
m 1915
n 1590
O 1
o 10983
p 2127
P 3
Q 11
q 118
r 14003
S 1
s 2559
T 2
t 8165
u 1067
v 595
w 4556
X 4
x 7802
y 660
z 193
ź 48
一次是大写在前,另一次是小写。有没有什么办法解决这一问题?
数字也很混乱......但这可以通过sort
(有时......为什么?......)进行排序。 Ubuntu 在这里,如果这很重要的话。
你可以看到整个脚本这里。
更新
我应用LANG=pl_PL.UTF-8 sort
到脚本中的函数。现在已经没有那么乱码了,但是小写和大写还是会出现乱码。
0 3359
1 7281
2 3931
3 2258
4 2046
5 1624
6 1882
7 1346
8 1892
9 846
A 1 #upper
a 2607 #then lower
b 578
c 1430 #lower
C 2 #then upper
D 1
...etc...
我的正常设置有所不同,但由子 shell 继承:
tomasz@tomasz-Latitude-E4200:~$ echo $LANG
en_US.UTF-8
tomasz@tomasz-Latitude-E4200:~$ (echo $LANG)
en_US.UTF-8
这使“正常”或以前的行为sort
变得困难。
不管怎样,当我在附加排序中明确使用 LANG 定义后,大小写也仍然是乱码,即:
ll /usr/bin | charstat | LANG=pl_PL.UTF-8 sort
这又产生了这个序列:
A 1
a 2607
b 578
c 1430
C 2
更新
$ locale
LANG=en_US.UTF-8
LANGUAGE=en_US
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC=pl_PL.UTF-8
LC_TIME=pl_PL.UTF-8
LC_COLLATE="en_US.UTF-8"
LC_MONETARY=pl_PL.UTF-8
LC_MESSAGES="en_US.UTF-8"
LC_PAPER=pl_PL.UTF-8
LC_NAME=pl_PL.UTF-8
LC_ADDRESS=pl_PL.UTF-8
LC_TELEPHONE=pl_PL.UTF-8
LC_MEASUREMENT=pl_PL.UTF-8
LC_IDENTIFICATION=pl_PL.UTF-8
LC_ALL=
答案1
问题不是bash
,问题是sort
。
现在sort
是语言环境意识到的。
如果您运行该locale
命令,那么它可能会显示类似的内容en_US
(如果您在美国;其他语言有其他区域设置)。还可能有编码 ( en_US.UTF8
)。
现在,语言环境也会影响排序。
让我们举一个简单的例子:
$ x="a\nA\nc\nC\nb\nB\n"
$ echo -ne "$x" | LANG=C sort
A
B
C
a
b
c
这看起来正是我们想要的。但...
$ echo -ne "$x" | LANG=en_US sort
a
A
b
B
c
C
呃哦!
sort
不是唯一可以根据区域设置更改行为的程序。
如果您希望跨设置的行为保持传统一致,那么您需要LANG
自行设置。
这并不罕见,您的操作系统可能已经将其作为其自己的脚本的一部分执行此操作。
例如...
在 RedHat/CentOS 上,很多/etc/rc.d/init.d
脚本都执行此操作;例如/etc/rc.d/init.d/network
有
interfaces=$(ls ifcfg* | \
LANG=C sed -e "$__sed_discard_ignored_files" \
-e '/\(ifcfg-lo$\|:\|ifcfg-.*-range\)/d' \
-e '/ifcfg-[A-Za-z0-9#\._-]\+$/ { s/^ifcfg-//g;s/[0-9]/ & /}' | \
LANG=C sort -k 1,1 -k 2n | \
LANG=C sed 's/ //')
在 debian 上,在开头/etc/init.d/exim4
设置LANG=C
,以及/usr/bin
.