固定幅ファイルをCSVに変換し、末尾のスペースを削除します。

固定幅ファイルをCSVに変換し、末尾のスペースを削除します。

私の入力ファイルは次のとおりです

$ cat -e myfile.txt 
999a bcd efgh555$
 8 z         7  $
1  xx xx xx  48 $

列に末尾のスペースがないCSVが必要です。

999,a bcd efgh,555
 8,z,7
1,xx xx xx,48

これまでに必要な場所に昏睡状態を正常に追加しました。

$ gawk '$1=$1' FIELDWIDTHS="3 10 3" OFS=, myfile.txt
999,a bcd efgh,555
 8 ,z         ,7  
1  ,xx xx xx  ,48 

末尾のスペースをどのように削除できますか?

編集する:データにすでにカンマがある可能性があるため、次のことを行う必要があります。 (i)フィールドを二重引用符で囲みます。 (ii) 以下を使用します\"(または""以下に従います.RFC 4180)。たとえばa,aab"bbccc-> "a,aa","b\"bb","ccc"

  • gawk(同様にawk)を使用できます。
  • 他のソリューション(たとえば)も開いていますperl
  • gawk ... | sed ...処理する大容量ファイルが多いため、効率的なソリューション(例:not)が必要です。
  • フィールドの幅を知っているので、FIELDWIDTHS自動計算は不要です。

ベストアンサー1

そしてperl

<your-file perl -C -lnse 'print map {s/\s+$//r} unpack "a3a10a3"' -- -,=,

unpack()gawkと同じ処理を行いますFIELDWIDTHS

$,ここで、awkに対応するものはwithにOFS設定され、パラメータがに割り当てられていることがわかります。または、awkのようにこれを省略して最初にステートメントを追加することもできます。,-,=,-s-var=valuevalue$var-sBEGIN{$, = ","}BEGIN{OFS = ","}-v OFS=,

-Cロケールが文字マップとしてUTF-8を使用している場合、入力はUTF-8エンコードとして扱われ、最近ではほとんど使用されていないさまざまなマルチバイト文字マップを持つロケールは無視されます。

見つかったとおりに切り取りたい空白文字がすべてASCII文字である場合は、末尾のASCII空白(およびNUL)を削除するのではなく、A指定子を使用して単純化できます。aunpack()

<your-file perl -C -lnse 'print unpack "A3A10A3"' -- -,=,

それは文字数を考えてみてください。

バイト数は削除してください-C

子牛クラスターの数unpack "a3a10a3"はで置き換えることができます/^(\X{3})(\X{10})(\X{3})/

表示幅の場合、各文字の幅(幅0、単一幅、および二重幅文字を含む、TAB1、CR ...などの制御文字はサポートされていません)を考慮して、次のことがzshできます。 :

widths=(3 10 3)
while IFS= read -ru3 line; do
  csv=()
  for width in $widths; do
    field=${(mr[width])line}
    line=${line#$field}
    csv+=("${(M)field##*[^[:space:]]}")
  done
  print -r -- ${(j[,])csv}
done 3< your-file

ライトパッドの場合、r[width] rテキストを指定された幅にカットする場合、mこれは文字数ではなく表示幅に基づいて行われ、${(M)field##*[^[:space:]]}モードに基づいて前半まで拡張されます。空白(同じ必要はありません)。$fieldM${field%%[[:space:]]#}set -o extendedglob

おそらくよりもはるかに遅くなりますperl

ファイルにASCIIテキストのみが含まれている場合(例のように)、すべて同じでなければなりません。その後、-Cforを削除するか、perlロケールをC/に設定するPOSIXsedパフォーマンスが向上する可能性があります。gawkperl

UTF-8ロケールで入力が100000回繰り返されました。ここでは、1.1秒perl(変形0.34 A、変形1.7 \X)、Paulの1.3秒gawk、zsh 31秒、GNU sed 's/./&,/13;s/./&,/3;s/[[:space:]]*,/,/g;s/[[:space:]]*$//'(標準)2.1秒、1.1はsed -E 's/^(.{3})(.{10})/\1,\2,/;s/\s+,/,/g;s/\s+$//'(非標準)です。

C言語環境では、それぞれ0.9(0.27、1.2)、0.7、31、1.3、0.5になります。


これらのフィールドには、,または"文字が含まれていないと仮定します。一部のCSV形式には、先頭または末尾のスペースを含む引用フィールドも必要です。

正しいCSV出力を生成するための最も簡単な方法は、Text::CSV次のモジュールを使用することですperl

<your-file perl -C -MText::CSV -lne '
  BEGIN{$csv = Text::CSV->new({binary => 1})}
  $csv->print(*STDOUT, [unpack "A3A10A3"])'

基本的に、

  • 区切り記号は次のとおりです。,
  • 引用符は"..."
  • """引用符で脱出
  • 参照が必要なフィールドのみ参照

しかし、これはnew()即座に調整することができます。perldoc Text::CSV詳細より。


1特にTABの場合、入力を前処理してexpandこれらのTABを他の項目の空白シーケンスに変換できますが、この概念は次のとおりです。適用が難しく、テキストが送信される表示装置に依存することが多い。

おすすめ記事