sed
CSVファイルに対して次の操作をどのように使用または実行できますかawk
?
- 列を削除
- 列のコピー
- 1列移動
200行以上の大きなテーブルがありますsed
。
答え1
CSVファイルがカンマのみを区切り文字として使用するのか、それとも次のようなクレイジーな内容があるのかによって異なります。
フィールド 1、「フィールド、2」、フィールド 3
単純なCSVファイルを使用するとします。
列を削除
さまざまな方法で個々の列を削除できます。たとえば、列2を使用します。最も簡単な方法はおそらくを使用することですcut
。これにより、印刷する区切り文字-d
とフィールドを指定できます-f
。これにより、コンマに分割してフィールド1とフィールド3を最後まで出力します。
$ cut -d, -f1,3- /path/to/your/file
必ず使用する必要がある場合は、最初のフィールド、3番目のフィールド、および残りのフィールドを一致させる正規表現を作成し、2番目のフィールドの出力をスキップsed
できます(ここでは2なので、最初のグループは一致時間です)。n-1
n
n
n
1
\{1\}
$ sed 's/\(\([^,]\+,\)\{1\}\)[^,]\+,\(.*\)/\1\3/' /path/to/your/file
これを行うにはいくつかの方法がありますが、awk
その中に特にエレガントな方法はありません。ループを使用できますが、for
末尾のコンマを処理するのは次のように痛いです。
$ awk -F, '{for(i=1; i<=NF; i++) if(i != 2) printf "%s,", $i; print NL}' /path/to/your/file
フィールド1を出力し、それを使用してsubstr
フィールド2以降のすべてを完了する方が簡単です。
$ awk -F, '{print $1 "," substr($0, length($1)+length($2)+3)}' /path/to/your/file
しかし、追加の列では面倒です。
列のコピー
これはデフォルトでsed
は以前と同じ式ですが、ターゲット列をキャプチャし、代替項目にグループを複数回含めます。
$ sed 's/\(\([^,]\+,\)\{1\}\)\([^,]\+,\)\(.*\)/\1\3\3\4/' /path/to/your/file
forループ方式では、awk
次のようになります(やはり末尾のコンマを無視します)。
$ awk -F, '{
for(i=1; i<=NF; i++) {
if(i == 2) printf "%s,", $i;
printf "%s,", $i
}
print NL
}' /path/to/your/file
方法substr
:
$ awk -F, '{print $1 "," $2 "," substr($0, length($1)+2)}' /path/to/your/file
(tcdylはより良いアプローチを提案しました。彼の答え)
列の移動
このソリューションは他のソリューションに自然に従うと思いますsed
が、時間がかかり始めました。
答え2
awk
最高の選択です。awk
フィールドを数字で印刷する...
awk 'BEGIN { FS=","; OFS=","; } {print $1,$2,$3}' file
列を印刷せずに削除するには:
awk 'BEGIN { FS=","; OFS=","; } {print $1,$3}' file
順序を変更するには:
awk 'BEGIN { FS=","; OFS=","; } {print $3,$1,$2}' file
出力ファイルにリダイレクトします。
awk 'BEGIN { FS=","; OFS=","; } {print $3,$1,$2}' file > output.file
awk
出力をフォーマットすることもできます。
答え3
フィールドを切り取り、並べ替える方法(他の回答でダールーム)に加えて、奇妙なCSVフィールドの問題もあります。
あなたのデータがこの「奇妙な」カテゴリに属している場合今後そして郵便はがきフィルタリングすると問題を解決できます。以下のフィルタでは、文字、、、\x01
は\x02
データのどこにも表示されません。 \x03
\x04
awk
以下は単純なフィールドダンプのフィルタです。
メモ: 五つのゲーム無効または不完全な「参照フィールド」レイアウトがありますが、行の終わりには問題ありません(CSVパーサーによって異なります)。しかし、もちろん、これは次のような結果につながります。問題のある予期しない結果現在の状態から変更する場合行末場所。
修正する。ユーザー 121196末尾の引用符の前にコンマが続くエラーが指摘されました。ここに修正があります。
データ
cat <<'EOF' >file
field one,"fie,ld,two",field"three","field,\",four","field,five
"15111 N. Hayden Rd., Ste 160,",""
EOF
パスワード
sed -r 's/^/,/; s/\\"/\x01/g; s/,"([^"]*)"/,\x02\1\x03/g; s/,"/,\x02/; :MC; s/\x02([^\x03]*),([^\x03]*)/\x02\1\x04\2/g; tMC; s/^,// ' file |
awk -F, '{ for(i=1; i<=NF; i++) printf "%s\n", $i; print NL}' |
sed -r 's/\x01/\\"/g; s/(\x02|\x03)/"/g; s/\x04/,/g'
出力:
field one
"fie,ld,two"
field"three"
"field,\",four"
"field,five
"15111 N. Hayden Rd., Ste 160,"
""
ここにいる事前フィルタ、コメントで拡張します。
これポストフィルターただ反転\x01
。\x02
、、、\x03
\x04
sed -r '
s/^/,/ # add a leading comma delimiter
s/\\"/\x01/g # obfuscate escaped quotation-mark (\")
s/,"([^"]*)"/,\x02\1\x03/g # obfuscate quotation-marks
s/,"/,\x02/ # when no trailing quote on last field
:MC # obfuscate commas embedded in quotes
s/\x02([^\x03]*),([^\x03]*)/\x02\1\x04\2/g
tMC
s/^,// # remove spurious leading delimiter
'
答え4
CSVデータを処理するには、通常、次のCSV認識ツールを使用するのが最善です。ミラーまたはcsvkit。 CSV、引用規則などについて全く知らない一般的なテキスト処理ユーティリティですsed
。awk
テストデータ:
id,name,date of birth
1,"Alfonso, the first",1980-01-01
2,"Betty, the second",1980-01-02
3,"Conny, the third",1982-02-21
name
csvkitツールを使用してこのフィールドを削除するには:
$ csvcut -C name file
id,date of birth
1,1980-01-01
2,1980-01-02
3,1982-02-21
csvkitを使用してフィールドをコピーするには、次の手順を実行しますname
。
$ csvcut -c id,name,name,"date of birth" file
id,name,name,date of birth
1,"Alfonso, the first","Alfonso, the first",1980-01-01
2,"Betty, the second","Betty, the second",1980-01-02
3,"Conny, the third","Conny, the third",1982-02-21
まずdate of birth
、csvkitを使用してフィールドを移動するには、次の手順を実行します。
$ csvcut -c "date of birth",id,name file
date of birth,id,name
1980-01-01,1,"Alfonso, the first"
1980-01-02,2,"Betty, the second"
1982-02-21,3,"Conny, the third"
Millerを使用してこのフィールドを削除するには、次の手順を実行しますname
。
$ mlr --csv cut -x -f name file
id,date of birth
1,1980-01-01
2,1980-01-02
3,1982-02-21
Millerを使用してフィールドをコピーするにはname
(name2
最後に新しいフィールドとして作成されます):
$ mlr --csv put '$name2 = $name' file
id,name,date of birth,name2
1,"Alfonso, the first",1980-01-01,"Alfonso, the first"
2,"Betty, the second",1980-01-02,"Betty, the second"
3,"Conny, the third",1982-02-21,"Conny, the third"
date of birth
Miller を使用してレコードの先頭に移動するには:
$ mlr --csv reorder -f "date of birth" file
date of birth,id,name
1980-01-01,1,"Alfonso, the first"
1980-01-02,2,"Betty, the second"
1982-02-21,3,"Conny, the third"