排序不使用管道“|”对行进行排序正确地在其中

排序不使用管道“|”对行进行排序正确地在其中

我正在尝试对一些简单的管道分隔数据进行排序。然而,排序实际上并不是排序。它将我的标题行移动到底部,但以 241 开头的两行被以 24 开头的行分割。

cat sort_fail.csv
column_a|column_b|column_c
241|212|20810378
24|121|2810172
241|213|20810376

sort sort_fail.csv
241|212|20810378
24|121|2810172
241|213|20810376
column_a|column_b|column_c

列标题被移动到文件的底部,因此排序显然正在对其进行处理。但是,实际值并未按照我的预期进行排序。

在这种情况下,我解决了这个问题

sort sort_fail.csv --field-separator='|' -k1,1

但是,我觉得应该没有这个必要。为什么排序不排序?

答案1

sort是区域设置感知的,因此根据您的 LC_COLLATE 设置(从 LANG 继承),您可能会得到不同的结果:

$ LANG=C sort sort_fail.csv 
241|212|20810378
241|213|20810376
24|121|2810172
column_a|column_b|column_c

$ LANG=en_US sort sort_fail.csv
241|212|20810378
24|121|2810172
241|213|20810376
column_a|column_b|column_c

这可能会导致脚本出现问题,因为您可能不知道调用区域设置是什么,因此可能会得到不同的结果。

脚本强制执行所需设置的情况并不罕见

例如

$ grep 'LC.*sort' /bin/precat
      LC_COLLATE=C sort -u | prezip-bin -z "$cmd: $2"

现在有趣的是,这个|角色看起来很奇怪。

但这是因为 en_US 的默认规则(源自 ISO)表示

$ grep 007C /usr/share/i18n/locales/iso14651_t1_common
<U007C> IGNORE;IGNORE;IGNORE;<j> # 142 |

这意味着该|角色是被忽略并且排序顺序就像该字符不存在一样。

$ tr -d '|' < sort_fail.csv | LANG=C sort
24121220810378
241212810172
24121320810376
column_acolumn_bcolumn_c

这与您看到的“意外”排序相匹配。

解决方法是使用-n(强制数字排序),或使用字段分隔符(如您所做的那样)或使用区域设置C

答案2

令我恼火的是, 并24没有从两者之间的位置移动241。第二个字段以1.尝试4在第二个字段中进行领先排序,24被向下移动,所以我怀疑sort只是忽略了|除非另有说明。尝试sort -n...

答案3

-n, --numeric-sort 根据字符串数值进行比较

210
23

如果没有 -n,文本中的 210 会领先于 23,因为它是我的角色。

相关内容