bash 中的错误按不同的列排序?
bug in bash sort with different columns?
我正在处理一个文件,该文件包含 3 个值、一个 ID(如果您好奇的话,它们恰好是蛋白质 ID)、一个值,然后是另一个值。它是制表符分隔的,因此看起来像这样:
A2M 0.979569315988908 1
AACS 0.925340159491081 1
AAGAB 0.982296215686199 1
AAK1 0.736903840140103 1
AAMP 0.00589711816127862 0.138868449447202
AARS2 1 1
AARS 3.13300124295614e-05 0.00212792325492566
AARSD1 0.527417792161261 1
AASDH 0.869909252023668 1
AASDHPPT 0.763918221284724 1
AATF 0.691907759125663 1
ABAT 0.989693691462661 1
ABCA1 0.601194017450064 1
ABCA5 1 1
ABCA6 1 1
我有兴趣按字母顺序对这些 ID 进行排序并提取各种值。但是,我注意到 sort 对 ID 的排序方式不同,具体取决于我提取的内容。当我执行时:
cut --fields\=1,2 input.txt|sort --key=1
生成的文件是:
A2M 0.979569315988908
AACS 0.925340159491081
AAGAB 0.982296215686199
AAK1 0.736903840140103
AAMP 0.00589711816127862
AARS2 1
AARS 3.13300124295614e-05
AARSD1 0.527417792161261
AASDH 0.869909252023668
AASDHPPT 0.763918221284724
AATF 0.691907759125663
ABAT 0.989693691462661
ABCA1 0.601194017450064
ABCA5 1
ABCA6 1
但是当我执行时:
cut --fields\=1,3 input.txt|sort --key=1
我明白了
A2M 1
AACS 1
AAGAB 1
AAK1 1
AAMP 0.138868449447202
AARS 0.00212792325492566
AARS2 1
AARSD1 1
AASDH 1
AASDHPPT 1
AATF 1
ABAT 1
ABCA1 1
ABCA5 1
ABCA6 1
注意 AARS 和 AARS2 的位置调换了,这是不应该的,因为我只是根据第一列进行排序。我从 sort 中从未见过这样的行为,我已经使用 bash 一段时间了。这是一个错误,还是我做错了什么?
我认为排序是跳过选项卡...最终效果是 AARS0.00212792325492566 在 AARS21 之前,但 AARS21 在 AARS3.13300124295614e-05 之前。参见 this quesiton。
以下应该有效
cut -f1,2 input.txt | sort -t$'\t'
不幸的是它没有,但我认为剥离标签是导致问题的原因。
--key=1
选项告诉 sort
使用从第一行到末尾的所有 "fields" 对输入进行排序。正如 @rici 首先观察到的,默认情况下这是一种区域设置敏感排序,并且在许多区域设置中,出于整理目的,空格会被忽略。这似乎就是这里发生的事情。
如果你只想 对蛋白质 ID 进行排序,那么应该是这样的:
cut --fields=1,2 input.txt | sort --key=1,1
cut --fields=1,3 input.txt | sort --key=1,1
@rici 解释了如何通过指定考虑空白的排序顺序来解决问题。
您正在使用区域设置感知排序(这是默认设置)。在许多语言环境中,空白在整理顺序中被明确忽略;结合您的键从第一个字段延伸到行尾的事实(这意味着 --key
选项是多余的),实际上意味着这些行被排序,就好像这些字段被连接起来而没有干预空格。
这里有一个更长的解释:
我的偏好是使用 LC_COLLATE=C sort ...
进行非语言环境感知排序。 (例如,定义 alias csort="LC_COLLATE=C sort"
)。在这种情况下,您也可以使用 -k1,1
显式终止排序键。如果您的第一列是唯一的,那就足够了。
我正在处理一个文件,该文件包含 3 个值、一个 ID(如果您好奇的话,它们恰好是蛋白质 ID)、一个值,然后是另一个值。它是制表符分隔的,因此看起来像这样:
A2M 0.979569315988908 1
AACS 0.925340159491081 1
AAGAB 0.982296215686199 1
AAK1 0.736903840140103 1
AAMP 0.00589711816127862 0.138868449447202
AARS2 1 1
AARS 3.13300124295614e-05 0.00212792325492566
AARSD1 0.527417792161261 1
AASDH 0.869909252023668 1
AASDHPPT 0.763918221284724 1
AATF 0.691907759125663 1
ABAT 0.989693691462661 1
ABCA1 0.601194017450064 1
ABCA5 1 1
ABCA6 1 1
我有兴趣按字母顺序对这些 ID 进行排序并提取各种值。但是,我注意到 sort 对 ID 的排序方式不同,具体取决于我提取的内容。当我执行时:
cut --fields\=1,2 input.txt|sort --key=1
生成的文件是:
A2M 0.979569315988908
AACS 0.925340159491081
AAGAB 0.982296215686199
AAK1 0.736903840140103
AAMP 0.00589711816127862
AARS2 1
AARS 3.13300124295614e-05
AARSD1 0.527417792161261
AASDH 0.869909252023668
AASDHPPT 0.763918221284724
AATF 0.691907759125663
ABAT 0.989693691462661
ABCA1 0.601194017450064
ABCA5 1
ABCA6 1
但是当我执行时:
cut --fields\=1,3 input.txt|sort --key=1
我明白了
A2M 1
AACS 1
AAGAB 1
AAK1 1
AAMP 0.138868449447202
AARS 0.00212792325492566
AARS2 1
AARSD1 1
AASDH 1
AASDHPPT 1
AATF 1
ABAT 1
ABCA1 1
ABCA5 1
ABCA6 1
注意 AARS 和 AARS2 的位置调换了,这是不应该的,因为我只是根据第一列进行排序。我从 sort 中从未见过这样的行为,我已经使用 bash 一段时间了。这是一个错误,还是我做错了什么?
我认为排序是跳过选项卡...最终效果是 AARS0.00212792325492566 在 AARS21 之前,但 AARS21 在 AARS3.13300124295614e-05 之前。参见 this quesiton。
以下应该有效
cut -f1,2 input.txt | sort -t$'\t'
不幸的是它没有,但我认为剥离标签是导致问题的原因。
--key=1
选项告诉 sort
使用从第一行到末尾的所有 "fields" 对输入进行排序。正如 @rici 首先观察到的,默认情况下这是一种区域设置敏感排序,并且在许多区域设置中,出于整理目的,空格会被忽略。这似乎就是这里发生的事情。
如果你只想 对蛋白质 ID 进行排序,那么应该是这样的:
cut --fields=1,2 input.txt | sort --key=1,1
cut --fields=1,3 input.txt | sort --key=1,1
@rici 解释了如何通过指定考虑空白的排序顺序来解决问题。
您正在使用区域设置感知排序(这是默认设置)。在许多语言环境中,空白在整理顺序中被明确忽略;结合您的键从第一个字段延伸到行尾的事实(这意味着 --key
选项是多余的),实际上意味着这些行被排序,就好像这些字段被连接起来而没有干预空格。
这里有一个更长的解释:
我的偏好是使用 LC_COLLATE=C sort ...
进行非语言环境感知排序。 (例如,定义 alias csort="LC_COLLATE=C sort"
)。在这种情况下,您也可以使用 -k1,1
显式终止排序键。如果您的第一列是唯一的,那就足够了。