2009-03-04 76 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. 打印出每個日期的行號。