排序| uniq | xargs grep ...行包含空格

时间:2009-03-04 21:11:16

标签: bash command-line scripting cygwin

我有一个逗号分隔文件“myfile.csv”,其中第5列是日期/时间戳。 (mm / dd / yyyy hh:mm)。 我需要列出包含重复日期的所有行(有很多)

我正在通过cygwin使用bash shell for 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或其他脚本语言执行此操作...但我固执的性质坚持认为我应该能够使用{{1}等标准命令行工具在bash中执行此操作}},sortuniqfindgrep等。

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

5 个答案:

答案 0 :(得分:10)

  1. sort -k5,5将对字段进行排序并避免剪切;
  2. uniq -f 4将忽略uniq的前4个字段;
  3. 在uniq上加上一个-D可以获得所有重复的行(vs -d,它只能让你一个);
  4. 但uniq会期望使用制表符分隔而不是csv,所以tr'\ t'','来修复它。
  5. 问题是如果#5之后的字段不同。你的约会时间长度是一样的吗?您可以将-w 16(包含时间)或-w 10(仅适用于日期)添加到uniq。

    所以:

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

答案 1 :(得分:2)

-z的{​​{1}}选项需要将输入分为NUL。您可以通过以下方式过滤uniq的输出:

cut

获得零分隔行。然后tr '\n' '\000' sortuniq可以选择处理该问题。尝试类似:

xargs

编辑:管道中cut -d, -f 5 myfile.csv | tr '\n' '\000' | sort -z | uniq -d -z | xargs -0 -I {} grep '{}' myfile.csv 的位置错误。

答案 2 :(得分: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循环中迭代它。)

答案 3 :(得分:0)

您可以使用-d选项告诉xargs使用每一行作为参数。尝试:

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

答案 4 :(得分: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. 打印出每个日期的行号。