csvに変換されたExcelファイルがあります。変換後は以下の例のようになります(csvには100を超える列があります。これは縮小版です)。
,Product," ",Citty," ",Price
,Name," ",Location," ",Per Unit
,banana," ",CA," ",5.7
,apple," ",FL," ",2.3
1行目と2行目を取得し、コンマの配置に従って「マージ」するスクリプトを作成する必要があります。
,Product Name," "" ",Citty Location," "" ",Price Per Unit
,banana," ",CA," ",5.7
,apple," ",FL," ",2.3
こことStack Overflowで他の質問を見ましたが、答えはファイルの最初の2行の奇妙な列別の状況とは関係がないようです。
無関係な追加操作でcsvから空の列を削除し、タイプミスを修正して次のように見せたいと思います。
Product Name,City Location,Price Per Unit
banana,CA,5.7
apple,FL,2.3
(csvには現在、各実際のデータ列の間に引用符で囲まれたタブがあります。ただし、最初の列は空で、後ろにカンマがあります。)
何度もタイプミスのあるCSVを受け取るので、スクリプトのエラーをプログラムで修正したいと思います。また、列は常に上記の順序で表示されない可能性があるため、スクリプト中に各列名にエラーがないことを動的に確認する必要があります。
答え1
この試み
$ awk -F, 'NR<2{split(gensub(/Citty/,"City","g",$0),a,FS)}NR==2{for(b=2;b<=NF;b+=2){c=c a[b]" "$b","}print gensub(/,$/,"",1,c)}NR>2{print gensub(/(^,|" *",)/,"","g",$0)}' inp
Product Name,City Location,Price Per Unit
banana,CA,5.7
apple,FL,2.3
$
同じコードを複数行に分割すると、読みやすくなります。
$ awk -F, '
> NR<2{split(gensub(/Citty/,"City","g",$0),a,FS)}
> NR==2{for(b=2;b<=NF;b+=2){c=c a[b]" "$b","}print gensub(/,$/,"",1,c)}
> NR>2{print gensub(/(^,|" *",)/,"","g",$0)}' inp
Product Name,City Location,Price Per Unit
banana,CA,5.7
apple,FL,2.3
$
最初の行の場合は、行をa内の配列要素に分割します。都市 - >都市スペルエラーを修正しました。
2行目の場合は、2列目から始めて、その列と一緒に1行目の対応する列を印刷します。各列に対してこの操作を2列ずつ繰り返します。末尾のエントリを削除します,
。
2行目以降は、,
前の項目またはすべての項目を"<spaces>",
空の文字列に置き換えて結果を印刷します。
GNU Awk 4.0.2でよくテストされました。
答え2
Perl、Text::CSV、および MoreUtils の使用:
perl -MText::CSV -MList::MoreUtils=pairwise -lne '
BEGIN { $p = Text::CSV->new(); }
@f = $p->fields() if $p->parse($_);
@hdr = map { s/Citty/City/ ; $_ } @f if $. == 1;
@f = pairwise { $a . " " . $b } @hdr, @f if $. == 2;
print join ",", grep { /\w/ } @f if $. > 1;
' file.csv
Product Name,City Location,Price Per Unit
banana,CA,5.7
apple,FL,2.3
grep
単語文字が1つも含まれていないフィールドは無視されます。
Perl> = 5.14.0を使用すると、置換を単純化して使用できますmap s/Citty/City/r @f
。ロスレス交換修飾子
答え3
努力する
awk -F, '
{gsub (/,*"[ ]*",*/, ",")
sub (/^,/, "")
sub (/Citty/, "City")
}
NR == 1 {n = split ($0, T)
next
}
NR == 2 {for (;n; n--) $n = T[n] " " $n
}
1
' OFS=, file
Product Name,City Location,Price Per Unit
banana,CA,5.7
apple,FL,2.3