在包含以下内容的文件中:
...
18-11-2018:othercharacters
10-11-2018:othercharacters
03-10-2018:othercharacters
30-10-2018:othercharacters
27-09-2018:othercharacters
03-12-2018:othercharacters
...
命令 :
sort -t- -k2 -k1
不按日期排序,我错过了什么?
答案1
这就是推荐日期格式为 YYYY-MM-DD 的原因之一。
-k2
对以第二个字段开头的行部分进行排序,您只需-k2,2
对第二个字段进行排序,因此:
sort -b -t- -k2,2 -k1,1
或者:
sort -b -k1.7,1.10 -k1.4,1.5 -k1.1,1.2
首先按年份排序(第一个字段的第 7 到第 10 个字符(在使用 , 忽略该字段中的前导空格后进行计数-b
,并使用默认字段分隔符(从非空白转换为空白))),然后按月份排序天。
答案2
使用-k2
withsort
将使实用程序使用从第二个字段开始的整行作为排序键。除非这个排序键不是唯一的,否则-k1
永远不会使用后者。要仅使用第二个字段作为第一个排序键,请使用-k2,2
。如果其他排序键不唯一(并且“整行”从第一个字段开始),则不需要添加-k1
或 ,因为默认情况下将使用整行作为排序键。-k1,1
sort
换句话说,以下三个命令是等效的:
sort -t - -k 2,2 -k 1,1 file
sort -t - -k 2,2 -k 1 file
sort -t - -k 2,2 file
以下是更通用的解决方案。
假设数据可以被解析为用作字段分隔符的“简单”无标头 CSV 文件:
,我们可以将第一个字段中的日期转换为新字段中的 Unix 时间戳,按该新字段排序,然后放弃该字段。这有时被称为施瓦茨变换。
使用磨坊主:
$ mlr --csvlite --fs : -N put '$key = strptime($1,"%d-%m-%Y")' then sort -f key then cut -x -f key file
27-09-2018:othercharacters
03-10-2018:othercharacters
30-10-2018:othercharacters
10-11-2018:othercharacters
18-11-2018:othercharacters
03-12-2018:othercharacters
该put
表达式创建一个命名字段,key
并使用调用结果进行strptime()
调用。这将是一个类似于1542499200.000000
(“2018-11-18”) 的 Unix 时间戳,表示自 1970-01-01 开始以来的秒数。然后我们sort
对该字段使用操作并用 删除它cut -x
。
答案3
作为更通用的年/月/日排序解决方案,您可以将最初的冒号 ( :
) 替换为冒号 + 破折号 ( -:
),按字段 3、2、1 排序,然后将冒号 + 破折号替换为冒号以结束。 (这将年份作为单独的字段与行的其余部分隔离,以便可以独立于行进行排序。它确实假设这种情况-:
不会出现在数据的前三个字段中。)
sed 's/:/-:/' file | sort -t'-' -k3,3 -k2,2 -k1,1 | sed 's/-:/:/'
虽然我很欣赏您似乎不需要使用您向我们展示的数据集对年份进行排序,但这是概括该问题的一种方法。