2009-03-04 16 views
4

私はカンマで区切られたファイル "myfile.csv"を持っています。ここで、5番目の列は日付/時刻スタンプです。 (mm/dd/yyyy hh:mm)。 私は ソート|ユニーク| xargs grep ...行に空白が含まれています

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

が正しく重複日付のリストを返すWinXPの

ためにcygwinの経由でbashシェルを使用してい

(たくさんある)重複した日付を含むすべての行をリストする必要が

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または他のスクリプト言語でこれを行うことができることを知っている...しかし、私の頑固な性質は、私がsortuniqfindgrepcutなどの標準的なコマンドラインツールを使用してbashでそれを行うことができるはずだと主張

教えて、oh bash gurus。典型的なcliツールを使用して必要な行のリストを取得するにはどうすればよいですか?

答えて

10
  1. sort -k5,5は、フィールドのソートを行い、カットを回避します。
  2. uniq -f 4はuniqの最初の4つのフィールドを無視します。
  3. uniqにプラス記号を付けると、すべての繰り返し行が表示されます(vs -dは1つだけ表示されます)。
  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。 CSV形式が重要な場合は最後にtr '\ t' '、'を入力します。 – kmkaplan

2

-zのオプションuniqは、入力をNULで区切る必要があります。ゼロ分離行を取得するには

tr '\n' '\000' 

:あなたはを通してcutの出力をフィルタリングすることができます。その後、sortuniq、およびxargsにはそれを処理するオプションがあります。

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' ---まさに私が探していたもの –

0

あなたは、-dオプションを使用してその全体に引数として各ラインを使用してxargsのを伝えることができます。試してみてください:

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」の配列に重複した日付の行を読んで、それを反復することです。ループ用)

+0

修正:sed式で2つのバックスラッシュを使用する必要があります echo 01/01/2005 00:37 | sed 's// \\\\/g' –

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. 空白の5番目のフィールドをスティックすると、結果はAになります。
  3. その日に既に格納されているもののリストに行番号を連結します。
  4. 各日付の行番号を印刷します。
関連する問題