Shell 按日期排序重复项
我有一个包含两列元素(id和date)的文件。我想根据id对这些元素进行排序,如果几个元素具有相同的id,它们将根据日期进行排序 我使用了Shell 按日期排序重复项,shell,sorting,unix,sh,Shell,Sorting,Unix,Sh,我有一个包含两列元素(id和date)的文件。我想根据id对这些元素进行排序,如果几个元素具有相同的id,它们将根据日期进行排序 我使用了sort-t”“-k2-t”/-k3-k2-k1 file.txt,但这不起作用。 我不知道如何使用字段分隔符 输入文件 01/02/2012 1 02/03/2012 1 04/04/2012 1 01/02/2015 2 02/03/2014 2 04/04/2013 2 输出文件应为: 01/02/2012 1
sort-t”“-k2-t”/-k3-k2-k1 file.txt
,但这不起作用。
我不知道如何使用字段分隔符
输入文件
01/02/2012 1
02/03/2012 1
04/04/2012 1
01/02/2015 2
02/03/2014 2
04/04/2013 2
输出文件应为:
01/02/2012 1
02/03/2012 1
04/04/2012 1
04/04/2013 2
02/03/2014 2
01/02/2015 2
坦白地说,我很确定你可以用一个复杂的表达式来指示
sort
理解日期,但你真的不应该
这是python中可读的几行代码;差不多
#!/usr/bin/env python2
from dateutil import parser
import sys
class comparable_line(object):
def __init__(self, line):
spacepos = line.find(" ")
if spacepos < 0:
raise ValueError("line must contain a space")
self._num = int(line[spacepos+1:])
self._date = parser.parse(line[:spacepos])
def __cmp__(self, other):
"""" comparison method that is automatically called by python """"
if self._num < other._num:
return -1
if self._num > other._num:
return 1
# at this point we know that the numbers are equal
if self._date < other._date:
return -1
if self._date > other._date:
return 1
# totally equal: return equality (0)
return 0
def __str__(self):
return "{num:d} {day:02d}/{month:02d}/{year:4d}".format(self._num, self._date.day, self._date.month, self._date.year)
sortedlines = [comparable_line(l) for l in sys.stdin].sort()
for line in sortedlines:
print line
会有用的 坦率地说,我很确定你可以用一个复杂的表达式来指示
sort
理解日期,但你真的不应该
这是python中可读的几行代码;差不多
#!/usr/bin/env python2
from dateutil import parser
import sys
class comparable_line(object):
def __init__(self, line):
spacepos = line.find(" ")
if spacepos < 0:
raise ValueError("line must contain a space")
self._num = int(line[spacepos+1:])
self._date = parser.parse(line[:spacepos])
def __cmp__(self, other):
"""" comparison method that is automatically called by python """"
if self._num < other._num:
return -1
if self._num > other._num:
return 1
# at this point we know that the numbers are equal
if self._date < other._date:
return -1
if self._date > other._date:
return 1
# totally equal: return equality (0)
return 0
def __str__(self):
return "{num:d} {day:02d}/{month:02d}/{year:4d}".format(self._num, self._date.day, self._date.month, self._date.year)
sortedlines = [comparable_line(l) for l in sys.stdin].sort()
for line in sortedlines:
print line
会有用的 想法:尝试使用一个字段分隔符(sort
不处理两个或多个不同的分隔符)
第一个sed
用/
分隔符将空格字符替换为/
而不是排序
,下一个sed
将最后一个/
替换为空格
我不知道您的日期格式是DD/MM/yyyyy
或MM/DD/yyyyy
,所以您可能希望在排序中使用repace-k4-k3-k2-k1
到-k4-k3-k1-k2
(我假设是第一个版本)。想法:尝试使用一个字段分隔符(排序
不能处理两个或更多不同的分隔符)
第一个sed
用/
分隔符将空格字符替换为/
而不是排序
,下一个sed
将最后一个/
替换为空格
我不知道您的日期格式是DD/MM/yyyyy
或MM/DD/YYYY
,所以您可能希望在排序中将-k4-k3-k2-k1
改为-k4-k3-k1-k2
(我假设是第一个版本)。与@uzsolt的答案类似,是一种施瓦茨变换
sed -r 's#([0-9]{2})/([0-9]{2})/([0-9]{4})#\3\2\1 &#' file |
sort -t " " -n -k 3,3 -k 1,1 |
cut -d " " -f 2-
第一个命令在行首添加一个更合理的日期:
01/02/2012 1 => 20120201 01/02/2012 1
然后按字段3和字段1进行简单的数字排序。
然后切断新添加的第一个字段。这与@uzzolt的答案类似,是一个Schwartzian变换
sed -r 's#([0-9]{2})/([0-9]{2})/([0-9]{4})#\3\2\1 &#' file |
sort -t " " -n -k 3,3 -k 1,1 |
cut -d " " -f 2-
第一个命令在行首添加一个更合理的日期:
01/02/2012 1 => 20120201 01/02/2012 1
然后按字段3和字段1进行简单的数字排序。
然后删除新添加的第一个字段。您的日期格式太糟糕了。是MM/DD/YYYY(据我所知,美国是地球上唯一使用这种格式的地方,而我们(世界其他地区)通常不喜欢这种格式,但美国确实占主导地位),还是DD/MM/YYYY(相对合理的格式,很遗憾,与美国的格式容易混淆)?@Marcus根据他的预期输出,我相信他使用DD/MM/YYYY。美国和加拿大使用的格式是MM/DD/YYYY:日期有一个标准——我希望每个人都能使用它!你的约会格式太糟糕了。是MM/DD/YYYY(据我所知,美国是地球上唯一使用这种格式的地方,而我们(世界其他地区)通常不喜欢这种格式,但美国确实占主导地位),还是DD/MM/YYYY(相对合理的格式,很遗憾,与美国的格式容易混淆)?@Marcus根据他的预期输出,我相信他使用DD/MM/YYYY。美国和加拿大使用的格式是MM/DD/YYYY:日期有一个标准——我希望每个人都能使用它!如果我们使用GNU sed,您的上一个sed可以简化:替换第三个斜杠:sed's,/,3'
此外,您可能希望更精确地指定字段:-k4,4-k3,3-k2,2-k1,1
——如编写的排序所示-k4,4-k3,4-k2,4-k1,4
。在这里,结果是一样的,但在其他情况下,这可能会咬到你。@glennjackman我使用的是FreeBSD的sed
-它不支持3
(数字)标志。那么sed-E的,(.*)/,\1',
——因为*
是贪婪的,我们知道我们已经有了最后一个斜杠。如果我们使用GNU sed,您的最后一个sed可以简化:替换第三个斜杠:sed's,/,3'
。此外,您可能希望更精确地指定字段:-k4,4-k3,3-k2,2-k1,1
——如书面排序所示-k4,4-k3,4-k1,4
。在这里,结果是一样的,但在其他情况下,这可能会咬到你。@glennjackman我使用的是FreeBSD的sed
-它不支持3
(数字)标志。那么sed-E的,(.*)/,\1',
-既然*
是贪婪的,我们知道我们已经有了最后一个斜杠了。