私の入力ファイルは次のとおりです
$ 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=value
value
$var
-s
BEGIN{$, = ","}
BEGIN{OFS = ","}
-v OFS=,
-C
ロケールが文字マップとしてUTF-8を使用している場合、入力はUTF-8エンコードとして扱われ、最近ではほとんど使用されていないさまざまなマルチバイト文字マップを持つロケールは無視されます。
見つかったとおりに切り取りたい空白文字がすべてASCII文字である場合は、末尾のASCII空白(およびNUL)を削除するのではなく、A
指定子を使用して単純化できます。a
unpack()
<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:]]}
モードに基づいて前半まで拡張されます。空白(同じ必要はありません)。$field
M
${field%%[[:space:]]#}
set -o extendedglob
おそらくよりもはるかに遅くなりますperl
。
ファイルにASCIIテキストのみが含まれている場合(例のように)、すべて同じでなければなりません。その後、-C
forを削除するか、perl
ロケールをC
/に設定するPOSIX
とsed
パフォーマンスが向上する可能性があります。gawk
perl
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を他の項目の空白シーケンスに変換できますが、この概念は次のとおりです。幅適用が難しく、テキストが送信される表示装置に依存することが多い。