Bash 排序规则强度(大写字符与小字符)

Bash 排序规则强度(大写字符与小字符)

我有一个读取输入并计算字符出现次数的脚本。它基于数组:

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.

相关内容