3

次のようなデータを含む CSV ファイルがあります。

1,275,,,275,17.3,0,"2011-05-09 20:21:45"
2,279,,,279,17.3,0,"2011-05-10 20:21:52"
3,276,,,276,17.3,0,"2011-05-11 20:21:58"
4,272,,,272,17.3,0,"2011-05-12 20:22:04"
5,272,,,272,17.3,0,"2011-05-13 20:22:10"
6,278,,,278,17.3,0,"2011-05-13 20:24:08"
7,270,,,270,17.3,0,"2011-05-13 20:24:14"
8,269,,,269,17.3,0,"2011-05-14 20:24:20"
9,278,,,278,17.3,0,"2011-05-14 20:24:26"

このファイルには、4432986 行のデータが含まれています。

最後の列の日付に基づいて新しいファイル名に基づいてファイルを分割したいと考えています。

したがって、上記のデータに基づいて、各ファイルの各日の行を含む 6 つの新しいファイルが必要になります。

YYYY_MM_DD 形式のファイル名が欲しいです。

出力データの最初の列も無視したい

したがって、ファイル 2011_05_13 には次の行が含まれ、最初の列は除外されます:-

272,,,272,17.3,0,"2011-05-13 20:22:10"
278,,,278,17.3,0,"2011-05-13 20:24:08"
270,,,270,17.3,0,"2011-05-13 20:24:14"

Linuxボックスでこれを行うことを計画しているので、Linuxユーティリティを使用するものは何でもクールで、sed awkなどですか??

4

6 に答える 6

6

これがあなたのためのワンライナーですawk

awk -F "," '{ split ($8,array," "); sub ("\"","",array[1]); sub (NR,"",$0); sub (",","",$0); print $0 > array[1] }' file.txt

おそらくこのコードの一部をより簡潔にすることができますが、望ましい出力が達成されました。HTH。

編集:

コードを左から右に読みます。

  • -F ","
    はい、これで区切り文字が設定されます。

  • split ($8,array," ")
    これにより、スペースの8番目の列が分割され、この情報が。という配列に配置されarrayます。

  • sub ("\"","",array[1])
    最初の配列要素(これは出力ファイル名になるスライスです)を取得し、先頭の"記号を置き換えます(記号をエスケープして、文字を前"に配置する必要があります)。\

  • sub (NR,"",$0)
    これにより、ファイルの先頭から行番号が削除されます(これNRは行番号で$0あり、もちろん区切り前の入力行全体です)。

  • sub (",","",$0)
    これにより、行番号の後のコンマが削除されます。

  • これで、クリーンなファイル名とクリーンなデータ行ができたので、次のように書き込むことが$0できarray[1]ますprint $0 > array[1]

修理:

したがって、ハイポンではなくアンダースコアを使用したい場合は、修正する必要があるのはarray[1]です。グローバル置換を追加しました:gsub ("-","_",array[1])

更新されたコードは次のとおりです。

awk -F "," '{ split ($8,array," "); sub ("\"","",array[1]); gsub ("-","_",array[1]); sub (NR,"",$0); sub (",","",$0); print $0 > array[1] }' file.txt

HTH。

于 2012-04-18T22:07:06.127 に答える
2

次の awk コマンドを使用できます。

awk -F, 'BEGIN{OFS=",";} {dt=$8; gsub(/^"| .*"$/,"", dt);
$1=""; sub(/^,/, "", $0); print $0 > dt}' input.txt
于 2012-04-18T22:11:51.900 に答える
1

ここでは、スクリプト言語 (perl/python) がおそらく最良の選択ですが、bash でこれを行うという課題が気に入ったので、ここで説明します。

 cat bigfile.txt | while read LINE;
  do echo $LINE >> `echo $LINE | cut -d, -f8 | cut -c2-11`.txt ;
 done

基本的に、これが行うことは、whileループ内でファイルを 1 行ずつ読み取り、その行を日付に基づいてファイルに追加することです。

日付は 2 つのコマンドの組み合わせで引き出されcutます。1 つ目cutはカンマ区切り文字 ( -d,) を使用して最後の列 (8 列目) を取り出し、次に 2 つ目cutは最初の を削除して日付だけを取り出し、"11 文字目まで丸呑みします。


次に、最初の列の削除に取り組みます。

cat bigfile.txt | sed 's/^.*?,//'

この正規表現は、最初のコンマより前のすべてを削除するだけです。

そのため、while ループの先頭をこれに置き換えて、次のようにします。

 cat bigfile.txt | sed 's/^.*?,//' | while read LINE;
  do echo $LINE >> `echo $LINE | cut -d, -f8 | cut -c2-11`.txt ;
 done
于 2012-04-18T20:57:51.640 に答える
1

この怪物はすべての一意の日付を取得し、元のファイルでそれらのキーを検索して、そのキーで名前が付けられたファイルに保存します。はい、猫の無駄な使用ですが、アクションを細分化しようとしています。

cat records.txt \
| cut -f8 -d, \
| cut -f1 -d ' ' \
| tr -d '"' \
| sort -u \
| while read DATE ; do \
    cat records.txt \
    | cut -f2- -d, \
    | egrep ",\"${DATE} [0-9]{2}:[0-9]{2}:[0-9]{2}\"" \
    > ${DATE}.txt
done
于 2012-04-18T20:58:35.853 に答える
0

シンプルに違いない

$ sed 's/^[0-9]*,//' your_gigantic_data.csv
于 2012-04-18T21:12:00.200 に答える
0

これはあなたのために働くかもしれません:

sed 's/^[^,]*,\(.*"\(....\)-\(..\)-\(..\).*\)/echo \1 >>\2_\3_\4.csv/' file | sh

または GNU sed:

sed 's/^[^,]*,\(.*"\(....\)-\(..\)-\(..\).*\)/echo \1 >>\2_\3_\4.csv/e' file
于 2012-04-18T22:36:05.467 に答える