对文件名排序时,ls
忽略-,_
.我希望它也能在排序中使用这些字符。
一个例子:
touch a1 a2 a-1 a-2 a_1 a_2 a.1 a.2 a,1 a,2
现在显示这些文件ls -1
:
a1
a_1
a-1
a,1
a.1
a2
a_2
a-2
a,2
a.2
我所期望的是这样的:
a1
a2
a,1
a,2
a.1
a.2
a_1
a_2
a-1
a-2
即我希望在排序时考虑非字母数字字符。
谁能解释这种行为?这种行为是由标准强制执行的吗?或者这是因为编码是UTF-8?
更新:看来这和UTF-8排序有关:
$ LC_COLLATE=C ls -1
a,1
a,2
a-1
a-2
a.1
a.2
a1
a2
a_1
a_2
答案1
编辑:添加了对使用 LC_COLLATE=C 排序的数据的测试
默认整理顺序将那些“标点类型”字符视为具有相同的值..Use LC_COLLATE=C
以代码点顺序对待它们..
for i in 'a1' 'a_1' 'a-1' 'a,1' 'a.1' 'a2' 'a_2' 'a-2' 'a,2' 'a.2' ;do
echo $i;
done |LC_COLLATE=C sort
输出
a,1
a,2
a-1
a-2
a.1
a.2
a1
a2
a_1
a_2
以下代码测试全部有效的基本多语言平面中的 UTF-8 字符(除了\x00和\x0a;为简单起见)
它将已知(生成的)升序序列中的文件与随机排序的文件进行比较,然后使用 LC_COLLATE=C 再次排序。结果表明,C序列与原始生成的序列相同。
{ i=0 j=0 k=0 l=0
for i in {0..9} {A..F} ;do
for j in {0..9} {A..F} ;do
for k in {0..9} {A..F} ;do
for l in {0..9} {A..F} ;do
(( 16#$i$j$k$l == 16#0000 )) && { printf '.' >&2; continue; }
(( 16#$i$j$k$l == 16#000A )) && { printf '.' >&2; continue; }
(( 16#$i$j$k$l >= 16#D800 &&
16#$i$j$k$l <= 16#DFFF )) && { printf '.' >&2; continue; }
(( 16#$i$j$k$l >= 16#FFFE )) && { printf '.' >&2; continue; }
echo 0x"$i$j$k$l" |recode UTF-16BE/x4..UTF-8 || { echo "ERROR at codepoint $i$j$k$l " >&2; continue; }
echo
done
done
done; echo -n "$i$j$k$l " >&2
done; echo >&2
} >listGen
sort -R listGen > listRandom
LC_COLLATE=C sort listRandom > listCsort
diff <(cat listGen; echo "last line of listOrig " ) \
<(cat listCsort; echo "last line of listCsort" )
echo
cmp listGen listCsort; echo 'cmp $?='$?
输出:
63485c63485
< last line of listOrig
---
> last line of listCsort
cmp $?=0
答案2
这与字符集无关。相反,是语言决定了排序规则。 libc 检查$LC_COLLATE
//$LC_ALL
中呈现的语言$LANG
并查找其排序规则(例如/usr/share/i18n/locales/*
GLibC)并按指示对文本进行排序。
答案3
我对 Debian 的默认排序选项遇到了完全相同的问题,对我来说,它忽略了一个逗号,这阻止了我有效地对 CSV 数据进行排序,从而对我的 AI 造成严重破坏。
解决方案是,sort
我需要强制排序似乎是的默认行为,而不是单独使用它-d, --dictionary-order
。
运行命令:
sort -V
解决我的问题并考虑逗号。
答案4
只是一条评论...我对我的排序规则(es_AR.utf8)有很大的兴趣,因为我不能使用'C',因为重音符号,最糟糕的是问题也出现在数据库postgresql中,在'10之间的句子中'和'10.1'包括(这是一个例子)我不期望的值'100'..我想我必须在每个查询中使用排序规则..在'10'和'10.Z之间选择'100' ' 显示 true 但 SELECT '100' BETWEEN '10' AND '10.Z' COLLATE "C" 显示 'false' 这是正确的(在我看来)