a.csv
、b.csv
およびという3つのファイルがありますc.csv
。
a.csv
内容があります
1234567,11111111111111111111111111111111111111111111111111
b.csv
同様の内容があります。
1234567845610111211111111111111111111111111
c.csv
内容があります
111111,22222222,3333333,,,44444444444444444444
上記のa.csv
3つのファイルのうち、2つの列を持つファイルにはnull値を含めないでください。残りのファイル(および)は、ファイルを含むb.csv
他のテキストファイルc.csv
の例にロードする必要があるという意味でのみ必要です。List.txt
b.csv
c.csv
,
コンマ()なしでファイルを削除するために次のコマンドを試しましたが、うまくいかないこともb.csv
考慮する必要があります。c.csv
grep -v "," *.csv |cut -d ":" -f1
提案したように、次のコマンドを試しましたが、2つの値列を持つファイルが表示されます。
awk -F"," 'NF==2 {print FILENAME}' *.csv
ただし、無効なファイルを別のファイルに書き込む必要がある場合は、いくつかの提案を教えてください。
提案どおりに次のことを試しましたが、成功しませんでした。
ls | grep -v $(awk -F"," 'NF==2 {print FILENAME}') *.csv|sort -u
私も一度やってみるように勧めました。
awk -F',' 'BEGINFILE{ok=1}!$1||!$2||NF!=2{ok=0; nextfile}ENDFILE{if(!ok)print FILENAME}' *.csv
ただし、これにより次のエラーが発生します。
awk: A statement occurred that is not valid.
The input line number is 1. The file is <Filename>
The source line number is 1.
2番目のフィールド値は長さが250文字でa.csv
、b.csv
...などのn個の値があります。
答え1
私が正しく理解したら、次のいずれかの条件で満足する行を含むファイルを削除したいと思います。
- フィールド 1 は空です。
!$1
- フィールド 2 は空です。
!$2
- 2つのフィールドはありません。
NF!=2
それから
awk -F',' 'BEGINFILE{ok=1}!$1||!$2||NF!=2{ok=0; nextfile}ENDFILE{if (ok) print FILENAME}' *.csv
ok=1
フラグを設定し、上記のいずれかの条件が満たされるまで各行を繰り返し、「間違った」行が見つかった場合はファイルを無効にし、行を解析せずにファイルの末尾ok=0
にジャンプしますnextfile
。
各ファイルの終わりにゼロ以外の場合にのみENDFILE
印刷されます。FILENAME
if (ok)
したがって、一致を無効にするには、最後のテストを反転してif (!ok)
印刷するだけです。
awk -F',' 'BEGINFILE{ok=1}!$1||!$2||NF!=2{ok=0; nextfile}ENDFILE{if (!ok) print FILENAME}' *.csv
編集する
出力でエラーを再現することはできませんgawk
(ファイル名をxxx.fileにリダイレクトするなど、以下を参照)。
bash --version
GNU bash, version 5.0.16(1)-release (x86_64-pc-linux-gnu)
awk --version
GNU Awk 5.1.0, API: 3.0 (GNU MPFR 4.0.2, GNU MP 6.2.0)
tail -n +1 *.csv;
awk -F',' 'BEGINFILE{ok=1}
!$1||!$2||NF!=2{ok=0; nextfile}
ENDFILE{gzout=(ok)?"ok":"banjaxed"; print FILENAME > gzout".files"}' *.csv ;
tail -n +1 *.files
==> a.csv <==
1234567,11111111111111111111111111111111111111111111111111
==> b.csv <==
1234567845610111211111111111111111111111111
==> c.csv <==
111111,22222222,3333333,,,44444444444444444444
==> banjaxed.files <==
b.csv
c.csv
==> ok.files <==
a.csv
単一フィールド長制限(1024)問題にならないでくださいawk
3,000文字のレコード制限に違反しない限り、この場合、awk
どちらもsed
操作に適したツールではないようです。
答え2
あるいは、grep
どちらも使用できず、次のものがあると仮定して使用してくださいsed
。grep
数千あたりのファイル数数千grep
行がかなり長いので、行全体をpingするのではなく、各行の最初の行だけを確認したいと思います。
すべての最初の行(ファイル名を含む)をインポートしてファイルに入れます。
head -n1 *.csv > list
各項目には、次のようにコンテキスト(ファイル名)行、最初の行、その後に空白行があります。
==> a.csv <==
1234567,11111111111111111111111111111111111111111111111111
==> b.csv <==
1234567845610111211111111111111111111111111
線に合ったパターンがあることがわかっているので、^[0-9.]+,[0-9.]+$
次のことができます。
grep -E -B1 "^[0-9]+,[0-9]+$" list | grep -oP "(?<= )[^, <]+" > ok.list
1 つ目は前のコンテキスト行grep
(一致するファイル名を含む) から一致を抽出し、2 番目はファイル名を抽出して目的のファイルにダンプします。list
-B1
ok.list
ok.list
最後に、以下を使用してフィルタリングできます。
ls *.csv | grep -Fvxf ok.list > banjaxed.list
固定文字列(正規表現ではありません)「-F」のファイルを使用してファイルをgrep
フィルタリングでき、完全一致はファイルを一致させるパターンのリストとして使用し、もちろん逆方向一致はフィルタ処理されたファイル列をOutにリダイレクトします。ok.list
ls
-x
-f
-v
banjaxed.list
それが少なくともお金の価値がない場合、私はおもちゃを取り除きます。