2017-08-20 51 views
0

我有一个包含两列元素(id和date)的文件。我想根据它的id对这些元素进行排序,并且在几个元素具有相同的id的情况下,它们将根据它们的日期进行排序。sort duplicates date wise

我用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 
+1

你的日期格式很糟糕。是MM/DD/YYYY(据我所知,美国是世界上唯一使用的地方,我们(世界其他地方)通常不喜欢这种格式,但美国真的是占统治地位),或者是DD/MM/YYYY(相对逻辑格式,可悲的是,与美国人混淆)? –

+0

@Marcus根据他的预期产出,我相信他使用DD/MM/YYYY。他们在美国和加拿大使用的格式是MM/DD/YYYY:http://calendars.wikia.com/wiki/Date_format_by_country –

+0

日期有一个标准 - 我希望每个人都可以使用它! https://开头XKCD。com/1179/ –

回答

1

想法:尝试使用一个字段分隔符(sort不处理两个或多个不同的分隔符)。

$ cat file                                
01/02/2012 1                                   
02/03/2012 1                                   
04/04/2012 1                                   
01/02/2015 2                                   
02/03/2014 2                                   
04/04/2013 2 
$ sed 's, ,/,' file | sort -t '/' -k4 -k3 -k2 -k1 | sed 's,\(.*\)/\([^/]*\),\1 \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 

第一sed/分离器代替空格字符/sort和下sed替换最后/空间。

,我不知道你的日期格式为DD/MM/YYYYMM/DD/YYYY左右,也许你想repace -k4 -k3 -k2 -k1sort-k4 -k3 -k1 -k2(我假设的第一个版本)。

+0

如果我们使用的是GNU sed,那么你的最后一个sed可以被简化:替换第三个斜线:'sed's,/,,3'' –

+1

另外,你可能想更精确地指定你的字段:'-k 4,4 -k 3,3 -k 2,2 -k 1,1' - 按书面分类看见'-k 4,4 -k 3,4 -k 2,4 -k 1,4'。在这里,结果是一样的,但在其他情况下,这可能会让你感到痛苦。 –

+1

@glennjackman我使用的是FreeBSD的'sed' - 它不支持'3'(number)标志。 – uzsolt

0

坦率地说,我敢肯定,你可以做一个复杂的表达式,可以指示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 

警告:所有的出于我的头。未经测试。但是这可以处理任意合理的日期格式(顺便说一句,这是一种糟糕的日期格式 - 是MM/DD/YYYY还是DD/MM/YYYY ???)。

因此,输入文件,如

2013-01-01/00:00:12 3 
2013-01-01/00:00:15 3 

会的工作!

1

类似的想法@ uzsolt的答案,一个使用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.
然后切断新添加的第一字段。