如何按同一列的两个子串排序:仅第二个字符反向、第三个字符正向
如何实现仅部分字段反向、其余字段正向的多键排序?
问题背景
我有如下格式的文本文件(第五列是类似fs1q、fp2q这样的字符串):
2836344588 ... ... N fs1q 2836344589 ... ... N fp2q 2836374222 ... ... N fp3q 2836374223 ... ... N fp6q 2836374224 ... ... N fp7q 2836384836 ... ... N fs2q 2836384837 ... ... N fp1q 2836384838 ... ... N fp4q 2836384839 ... ... N fp5q 2836384957 ... ... N fs3q 2836384958 ... ... N fs7q 2836404416 ... ... N fs5q 2836414186 ... ... N fs6q 2836434267 ... ... N fs4q
我需要按第五列的规则排序:
- 第二个字符按反向字母顺序排序(
s排在p之前) - 第三个字符按常规数字顺序排序(1→2→3…)
我尝试了命令:
sort -k5.2r -k5.3n filename
但得到的结果中第三个字符也被反向排序了:
2836384958 ... ... N fs7q 2836414186 ... ... N fs6q 2836404416 ... ... N fs5q 2836434267 ... ... N fs4q 2836384957 ... ... N fs3q 2836384836 ... ... N fs2q 2836344588 ... ... N fs1q 2836374224 ... ... N fp7q 2836374223 ... ... N fp6q 2836384839 ... ... N fp5q 2836384838 ... ... N fp4q 2836374222 ... ... N fp3q 2836344589 ... ... N fp2q 2836384837 ... ... N fp1q
我期望的正确输出是:
2836344588 ... ... N fs1q 2836384836 ... ... N fs2q 2836384957 ... ... N fs3q 2836434267 ... ... N fs4q 2836404416 ... ... N fs5q 2836414186 ... ... N fs6q 2836384958 ... ... N fs7q 2836384837 ... ... N fp1q 2836344589 ... ... N fp2q 2836374222 ... ... N fp3q 2836384838 ... ... N fp4q 2836384839 ... ... N fp5q 2836374223 ... ... N fp6q 2836374224 ... ... N fp7q
解决方案
你的问题出在-k5.2r的写法上:当你只指定起始位置5.2而不指定结束位置时,sort会把从该位置到字段末尾的所有内容作为排序键,并且对整个键应用反向排序规则——这就导致第三个数字也被反向了。
要解决这个问题,你需要明确限定每个排序键的范围,确保反向规则只作用于第二个字符,而第三个字符单独作为正向排序的键:
sort -k5.2,5.2r -k5.3,5.3n filename
命令解释
-k5.2,5.2r:仅针对第五列的第2个字符(即s/p所在的位置)进行反向字母排序,确保s组排在p组前面-k5.3,5.3n:仅针对第五列的第3个字符(数字部分)进行正向数字排序,让数字按1→7的顺序排列
运行这个命令后,就能得到你期望的输出结果。
内容的提问来源于stack exchange,提问作者Tench
相关产品推荐
相关产品推荐

