数字が二重引用符で囲まれ、一部には囲まれていないCSVファイルがあります。数字の負の記号のみを変更する必要がありました。次の負の記号を削除して最初に追加する必要がありました。
入力例:
column 1, column 2, column 3, column 4, column 5
12-,"455,365.44-","string with quotes-and with a comma in between","4,432",6787
出力例:
column 1, column 2, column 3, column 4, column 5
-12,"-455,365.44","string with quotes-and with a comma in between","4,432",6787
答え1
牛に似た一種の栄養awk
解決策:
awk -v FPAT='[^,"]+|"[^"]+"' '
NR==1; NR>1{
for (i=1; i<=NF; i++) {
if ($i~/^"?[0-9]+([0-9,.]+[0-9]+)?-"?$/) {
sub(/-/, "", $i);
sub(/[0-9]/, "-&", $i);
}
printf "%s%s",$i,(i==NF? ORS:",")
}
}' file.csv
-v FPAT='[^,"]+|"[^"]+"'
- フィールド値を定義する正規表現パターン$i~/^"?[0-9]+([0-9,.]+[0-9]+)?-"?$/
- フィールドに数字とマイナス記号が含まれていることを確認してください-
(数字は二重引用符で囲むことができます)。
出力:
column 1, column 2, column 3, column 4, column 5
-12,"-455,365.44","string with quotes-and with a comma in between","4,432",6787
答え2
CSVデータにはCSVパーサーが必要です。 Rubyには次のものがあります。
$ cat file.csv
12-,"455,365.44-","string with quotes-and with a comma in between","4,432",6787
$ ruby -rcsv -e '
CSV.foreach(ARGV.shift) do |row|
corrected = row.collect {|e| e.sub(/^([\d,.]+)-$/, "-\\1")}
puts CSV.generate_line(corrected)
end
' file.csv
-12,"-455,365.44",string with quotes-and with a comma in between,"4,432",6787
CSVジェネレータは、「引用符付き文字列」にカンマが含まれていないため、引用する必要はないと判断しました。
答え3
FPATなしのgawk
Awkソリューション:
NR==1;
NR > 1 {
$0 = $0","
while ($0) {
match($0, / *"[^"]*" *,|[^,]*,/)
f = substr($0,RSTART,RLENGTH-1) # save what matched in f
if (( f ~ /^"[0-9]([0-9,.]+[0-9]+)-"$/ ) ||
( f ~ /^[0-9]+[.]?[0-9]+-$/ ) ||
( f ~ /^[0-9]+-$/ )) {
sub(/-/, "", f);
sub(/[0-9]/, "-&", f);
}
$0 = substr($0, RLENGTH+1)
printf "%s%s", f, (0 == NF ? "\n" : ",")
}
}
提供されたサンプルファイルの出力は次のとおりです。
column 1, column 2, column 3, column 4, column 5
-12,"-455,365.44","string with quotes-and with a comma in between","4,432",6787
答え4
sed
サポートされている実装では、文字列フィールドに含まれる二重引用符が次のようにエンコードされ、これらの文字列フィールドに改行が含まれていないと-E
想定されます。""
sed -E '
:1
s/^(("[^"]*"|[^"])*,)?([0-9.]+)-(,|$)/\1-\3\4/;
s/^(("[^"]*"|[^"])*,)?"([0-9,.]+)-"(,|$)/\1"-\3"\4/
t1' < file
入力の性質に応じて、数値をより厳密に一致させることができます。たとえば、([0-9.]+)-
ここではonと一致します12-
が、とも一致します...-
。そのタイプの入力が入力に表示される可能性がある場合は、([0-9]*\.?[0-9]+)-
次のように変更できます。