テキストファイルの各行を調べて修正するためのawkスクリプトの作成に問題があります。
次の例を考えてみましょう。
$ cat employee.txt
"100","Thomas","Sales","5000"
"200","Jason","Technology","5500"
"300","Mayla",
"Technology","7000"
"400","Nisha","Marketing","9500"
"500","Randy","Techno
logy","6000"
"501","Ritu","Accounting","5400"
ご覧のとおり、一部の線が間違った地点で壊れているようです。パターンは次のようにする必要があります。
$ cat employee.txt
"100","Thomas","Sales","5000"
"200","Jason","Technology","5500"
"300","Mayla","Technology","7000"
"400","Nisha","Marketing","9500"
"500","Randy","Technology","6000"
"501","Ritu","Accounting","5400"
したがって、awkでパターンが従わないことを確認する方法があるかどうか疑問に思います。たとえば、各行のカンマ数を確認してから、改行をバックスペースとして指定する方法です。
こういう数百、数千行のファイルを受け取るので、壊れた行をいつも直す手作業がとても退屈だ。
SQLLDRを使用してテーブルにデータをロードするための制御ファイルを生成していますが、テキストファイルに改行が含まれているためエラーが発生します。だから私の解決策は、スクリプトを介して各行を変更することでした。
どんなアイデアがありますか?スクリプトがAwkにある必要はありません。
答え1
$ awk -F, 'FNR == 1 { nf = NF } { while (NF < nf || !/[^,]"$/) { line = $0; getline; $0 = line $0 }; print }' file
"100","Thomas","Sales","5000"
"200","Jason","Technology","5500"
"300","Mayla","Technology","7000"
"400","Nisha","Marketing","9500"
"500","Randy","Technology","6000"
"501","Ritu","Accounting","5400"
これは以下を使用awk
します最初の行に正しい数のフィールドがあると仮定そして、どのフィールドにもカンマを含めることはできません。また、どの行も持たないと仮定します。多すぎるつまり、行に追加の改行がある可能性がありますが、次/前の行にリンクされている行はありません。
フィールド数が間違った行(または"
最後のフィールドが分割されたことを意味する文字で終わらない行)が見つかった場合は、現在の行が変数に保存され、次の行がline
読み取られます。その後、現在の行は、読み込んだline
行を連結して更新されます。これは、正しい数のフィールドがあることで終わるまで続きます(複数の連続分割線の場合)。次に、再構成された行を印刷します。
NF
awk
現在のレコードのフィールド数を格納する特殊変数です(デフォルトでは、1つのレコードは1行です).この番号は、(現在のレコード)が割り当てられているとき、または新しいレコードを読み取ると$0
自動的に更新されます。このnf
変数は、最初の行から始まり、「正しいフィールド数」に設定された独自の変数です。
答え2
正規表現により、簡単にテキストを変更できます。
<input.csv perl -pe 's/^(.+)([^"])\n$/\1\2/g'
あなたのため
"100","Thomas","Sales","5000"
"200","Jason","Technology","5500"
"300","Mayla","Technology","7000"
"400","Nisha","Marketing","9500"
"500","Randy","Technology","6000"
"501","Ritu","Accounting","5400"
答え3
短い awk 方法:
awk -F, '{ printf "%s%s", $0, $NF ~ /^$|[^"]$/? "":ORS }' file
$NF ~ /^$|[^"]$/
- 最後のフィールドが$NF
空の文字列であるか^$
、二重引用符がない単語であることを確認してください。[^"]$
出力:
"100","Thomas","Sales","5000"
"200","Jason","Technology","5500"
"300","Mayla","Technology","7000"
"400","Nisha","Marketing","9500"
"500","Randy","Technology","6000"
"501","Ritu","Accounting","5400"
答え4
別のawk
解決策:
awk -F, 'NF==4 { print $0 }; NF!=4 { str= $0; getline; print str $0 }' employee.txt
"100","Thomas","Sales","5000"
"200","Jason","Technology","5500"
"300","Mayla","Technology","7000"
"400","Nisha","Marketing","9500"
"500","Randy","Technology","6000"
"501","Ritu","Accounting","5400"