用管道“ |”对未排序的行进行排序 正确地


17

我正在尝试对一些简单的以竖线分隔的数据进行排序。但是,排序实际上不是排序。它将标题行移到底部,但我的两行以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

但是,我觉得那不是必须的。为什么排序不排序?


2
使用LC_COLLATE=C sort。根据您的期望,您可能还需要LC_COLLATE=C sort -t'|' -n
mosvy

3
要对“ csv样式”数据进行排序,您可能要使用csvsortfrom csvkit,它可以正确处理引用的值。
巴库里

Answers:


32

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语言环境。


迷人。我确实看到了一些其他有关本地化的信息,但认为这会影响24与241的相对顺序,而不是这样。
user10777668

7
--debug选项对GNU排序特别有用,它指示用于比较的键(带下划线)
杰夫·谢勒

与--debug一起运行只强调了整行-排序包括管道字符,由于本地化而被设置为没有影响。这是一个很好的功能,但是在这种情况下并没有帮助我(我尝试过:)
user10777668

这就是我提到@ user10777668的原因-它表示sort正在使用整行,而不是停在我们认为是的字符处。
Jeff Schaller

我没想到它会停止。我期望它能够识别竖线字符并将其包含在排序中,因此对24 | 1和241的处理方式有所不同。我不确定--debug会如何改变它,实际上,因为它强调了| |。似乎它会积极分散真正的问题,即本地化导致管道字符被淹没
user10777668

1

令我恼火的是两者24并没有从两者之间移开241。第二个字段以开头1。尝试4在第二个字段中使用前导进行排序,则将24其向下移动,因此我怀疑除非另有说明,否则它们将sort忽略|。尝试sort -n...


1

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

210
23

如果没有-n,则按字符210会比字符23领先。


没错,但这不能解释管道字符的不同。其他答案表明,由于语言环境的原因,不将管道视为那里,因此下一位数字决定顺序。
Criggie '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.