2009-03-04 33 views
4

我有一个逗号分隔的文件“myfile.csv”,其中第五列是日期/时间戳。 (mm/dd/yyyy hh:mm)。 我需要列出sort | uniq | xargs grep ...行包含空格

我使用的是bash shell通过Cygwin为WinXP的

$ cut -d, -f 5 myfile.csv | sort | uniq -d 

正确返回重复日期列表包含重复日期(有很多)的所有行

01/01/2005 00:22 
01/01/2005 00:37 
[snip]  
02/29/2009 23:54 

但我无法弄清楚如何喂这给grep给我所有的行。 显然,我不能直接使用xargs,因为输出包含空格。我认为我可以做uniq -z -d,但由于某种原因,结合这些标志会导致uniq(显然)不会返回任何内容。

因此,考虑到

$ cut -d, -f 5 myfile.csv | sort | uniq -d -z | xargs -0 -I {} grep '{}' myfile.csv 

不行......我该怎么办?

我知道我可以在perl或其他脚本语言做到这一点......但我生性倔强坚持认为我应该能够使用标准的命令行工具来做到这一点在bashsortuniqfindgrepcut,等

教我,哦打击大师。如何使用典型的cli工具获取我需要的行列表?

回答

10
  1. sort -k5,5会对字段进行排序并避免剪切;
  2. uniq -f 4将忽略uniq的前4个字段;
  3. 在uniq上加上一个-D会得到你所有的重复行(vs -d,这会让你只有一行);
  4. 但uniq会期望制表符分隔而不是csv,所以tr'\ t'','来解决这个问题。

问题是如果您在#5之后有不同的字段。你的日期都一样长吗?您可能可以向uniq添加-w 16(包含时间)或-w 10(仅限日期)。

所以:

tr '\t' ',' < myfile.csv | sort -k5,5 | uniq -f 4 -D -w 16 
+0

是+1。和tr'\ t'',最后如果CSV格式很重要。 – kmkaplan 2009-03-05 11:15:22

2

-z选项uniq需要输入NUL分隔。您可以通过过滤的cut输出:

tr '\n' '\000' 

要获得零个分开行。然后sort,uniqxargs有选项来处理。尝试类似:

cut -d, -f 5 myfile.csv | tr '\n' '\000' | sort -z | uniq -d -z | xargs -0 -I {} grep '{}' myfile.csv 

编辑:在管道中的位置tr是错误的。

+0

tr'\ n''\ 000' ---正是我在找的 – 2011-05-07 08:21:37

0

你可以告诉xargs的使用每一行使用-d选项的全部参数。尝试:

cut -d, -f 5 myfile.csv | sort | uniq -d | xargs -d '\n' -I '{}' grep '{}' myfile.csv 
1

尝试用逃避的空间sed的:

echo 01/01/2005 00:37 | sed 's/ /\\ /g' 
cut -d, -f 5 myfile.csv | sort | uniq -d | sed 's/ /\\ /g' | xargs -I '{}' grep '{}' myfile.csv 

(另一种方法是重复的日期行读入IFS = $“\ n”阵列和遍历它for循环)

+0

更正:在sed表达式中应该是两个反斜杠 echo 01/01/2005 00:37 | sed's// \\\\/g' – 2009-03-05 14:47:41

0

这是一个很好的候选人AWK:

BEGIN { FS="," } 
{ split($5,A," "); date[A[0]] = date[A[0]] " " NR } 
END { for (i in date) print i ":" date[i] } 
  1. 将字段分隔符设置为','(CSV)。
  2. 在空格上分隔第五个字段,粘贴结果A.
  3. 将行号连接到我们已经为该日期存储的列表。
  4. 打印出每个日期的行号。