2012-04-18 1 views
0

私は、行を含むファイル(サイズが非常に大きい)を持っていて、各行にカンマで区切られたいくつかのフィールドがあります。awkユーティリティを使用して実装するシナリオ

このファイルから、いくつかのフィールドを抽出して新しい行にダンプする必要があります。しかし、ここで問題となるのは、最後の1つのフィールド(列)自体にカンマが含まれていますが、その特定のフィールドは二重引用符「some、thing」で示されています。

は私が例を挙げてみましょう: -

the, quick, brown, fox, jumps, right, over, the little, "lazy,dog" 

コンマで区切られているこのファイルの多くのそのような行があります。

その最後の列の中に多くのカンマがあるかもしれません、

は、今私は最後のものは確かに私が抽出したいされているため、そこからいくつかの列を抽出する必要があります。

私はawkを使うと思っていましたが、awkには区切り文字の区切りに制限がないようです。

pythonにはsplit()関数があり、ここではnoを制限できます。文字列の最後のインデックスに入ります。 012 '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '

また、二重引用符は最終出力から削除する必要があります。

私はawkを使用しようとしていました。awkは大容量のファイル処理に関しては私にとっては高速です。しかし、そのような種類のものを実装することは可能ですか、それは少し遅くなるように見えるループと分割のpythonicの方法で行く必要があります。

注: 1)の列は固定されています。

お勧めします。

+0

「怠け者の犬」の「、」を取り除くと、これはまだ最後の1列か2つになりますか?また、脇に、問題のファイルに対して列の数を可変または固定していますか? – Levon

+0

あなたのタイトル 'awkユーティリティを使用して実装するシナリオ 'は、あなたの質問に一致しません。 – MattH

答えて

2

pythonのcsvモジュールを使用してください。

with open('myfile.txt') as data: 
    for line in csv.reader(data): 
     print line[2], line[5] 

シームレスに引用符を処理します。

+0

はい、これは処理できますが、プロセッサを遅くする多くの入出力操作があります。 Isnt'd? – geek

+1

バッファリングする必要があります。あなたはこの解決策を試してawkがより速いのを見つけましたか?または、あなたはただ推測していますか? – Useless

+0

私はこの解決策を試しましたが、awkは各行の読み込み(非常に多くのI/Oを含むため)にこれを行うよりも非常に速く出力することを確認しました。あなたの経験が言うことは..私が読む必要があるそのような行が約5croreあるので。 – geek

3

これはPythonから離れませんが、特に最後の項目の引用符を削除したい場合は、csvのようです。

のtest.CSV:

ay,bee,cee,dee,"ee,eff" 
foo,bar,"baz,quux" 

テスト。PY:

#!/usr/bin/env python 

import csv 

fp = open('test.csv', 'r') 
for row in csv.reader(fp): 
    print row 
fp.close() 

出力:

['ay', 'bee', 'cee', 'dee', 'ee,eff'] 
['foo', 'bar', 'baz,quux'] 
+0

これはループ内のI/O操作を行います..私のファイルは非常に多くのプロセッサ時間がかかる非常に大きいです。 – geek

+1

@ user1080454:AWKは暗黙のループを使用します。 –

+0

mite be ..しかしawkと同じことをチェックしたところ、2〜3分で5croreの結果が得られました。この例外的なケースがそこになかったのであれば。そのような事件が発生しないのですか? – geek

0

ええ、そこにcsvファイルのように見える;)ここで

sed代替

sed 's/"\([^"]\+\)"\|\([^,]\+\), \?/\n\1\2/g' 

が、これはあなたに各トークンを与えるです新しい行で、どのトークンを選択するかを選択できます

$ echo 'the, quick, brown, fox, jumps, right, over, the little, "lazy,foo , bar, fpp,dog"' | sed 's/"\([^"]\+\)"\|\([^,]\+\), \?/\n\1\2/g' 

the 
quick 
brown 
fox 
jumps 
right 
over 
the little 
lazy,foo , bar, fpp,dog 

最初の行は

は、第一、第四と最後のフィールド

$ echo 'the, quick, brown, fox, jumps, right, over, the little, "lazy,foo , bar, fpp,dog"' | sed 's/"\([^"]\+\)"\|\([^,]\+\), \?/\n\1\2/g' | sed -n '2p;5p;$p' 
the 
fox 
lazy,foo , bar, fpp,dog 

はすべて一緒に入れて(とbashのを使用して)取得空で予告

while read -r; do 
    sed 's/"\([^"]\+\)"\|\([^,]\+\), \?/\n\1\2/g' <<< "$REPLY" | sed -n '2p;5p;$p' 
done < file 
0

はPythonのようです私にとってより良い選択のように。

csvモジュールはこれに最適です。私はcsvファイルを解析し、各行をデータベースに挿入するためにこのオーバーヘッドを使用して、数十万行を素早く処理することができます。引用符。

あなたは、分割方法、希望する場合:

>>> string = 'the, quick, brown, fox, jumps, right, over, the little, "lazy,dog"' 
>>> string = string.replace('"','').split(', ') # note the ', ' not ',' 
>>> print string 
['the', 'quick', 'brown', 'fox', 'jumps', 'right', 'over', 'the little', 'lazy,dog'] 

はそのままあなたの最後のフィールドを維持するだろうし。 awkを持つ

$ cat tmp 
the, quick, brown, fox, jumps, right, over, the little, "lazy,dog" 
$ cat tmp | awk 'BEGIN { FS = ", " } ; { print $9 }' 
"lazy,dog" 

があなたのフィールドを提供しますが、あなたはsedのためのパイプか何かする必要があると思いますので、引用符を削除しません。また

$ cat tmp | awk 'BEGIN { FS = ", " } ; { print $9 }' | sed 's/"//g' 
lazy,dog 

その後、もちろん、あなたはまだCLプログラムの一つがない場合でも、それはあなたがデータをやりたいです何でもしなければならない「 『』、」FSであることに改めて注意していません具体的なタスクは速く、私はそれが全体的により速いプロセスとより少ない頭痛の結果になることをPythonで保つことが分かった。

関連する問題