csvファイルのコマンドラインから個別に実行するときに完全に機能する2つのsedコマンドがあります。どちらもcsvファイル列の1つの小数点形式を変更し、小数点以下の桁数を2桁に丸めるように設計されています。
- 小数点以下の桁数が1つだけある数字に0を追加します。
sed -r -e 's/[0-9]\;[0-9]+\.[0-9]/&0/'
- 小数点以下 2 桁以上の丸め数:
sed -re 's/([0-9]+\.[0-9]{2})[0-9]+/\1/'
これで同時に適用できるようにsedスクリプトに入れたいと思います。私はfixed_floats.sedというスクリプトを作成しました。
#!/bin/sed
s/[0-9]\;[0-9]+\.[0-9]/&0/
s/(\[0-9]+\.[0-9]{2}\)[0-9]+/\1/
次のコマンドを使用して実行しようとすると:
sed -f fix_floats.sed titanic-passengers.csv
出力で何も変わらないようです。 (sedコマンドの正規表現が拡張されているため、うまくいかないのは、スクリプトの実行時に指定しなかったためです。)
次のコマンドを使用して実行しようとすると:
sed -E -f fix_floats.sed titanic-passengers.csv
次のエラーが発生します。
sed: file fix_floats.sed line 5: invalid reference \1 on `s' command's RHS
csvに効率的に適用できるように、拡張正規表現を使用してsedスクリプトを作成する方法に関する提案はありますか?
生出力:(関心のある列は行の最後の3番目の列です。)
356;No;3;Vanden Steen, Mr. Leo Peter;male;28.0;0;0;345783;9.5;;S
546;No;1;Nicholson, Mr. Arthur Ernest;male;64.0;0;0;693;26.0;;S
希望の出力:
356;No;3;Vanden Steen, Mr. Leo Peter;male;28.0;0;0;345783;9.50;;S
546;No;1;Nicholson,Mr.Arthur Ernest;male;64.0;0;0;693;26.00;;S
答え1
スクリプトの最後の行は、コマンドラインで実行されるスクリプトとは異なります。 2つのバックスラッシュを追加する理由はありません。
s/(\[0-9]+\.[0-9]{2}\)[0-9]+/\1/
しなければならない
s/([0-9]+\.[0-9]{2})[0-9]+/\1/
(また、最初のコマンドでセミコロンをエスケープする必要はありませんが、s///
単に無視されるので問題になりません。)
答え2
次のように浮動小数点数を書式設定できる言語を使用する方が簡単です。
$ awk -F ';' 'BEGIN { OFS=FS } { $(NF-2) = sprintf("%.2f", $(NF-2)) }; 1' file
356;No;3;Vanden Steen, Mr. Leo Peter;male;28.0;0;0;345783;9.50;;S
546;No;1;Nicholson, Mr. Arthur Ernest;male;64.0;0;0;693;26.00;;S
プログラムは最後から始まり、3番目のawk
区切りフィールドを小数点以下の2桁の浮動小数点数で書き換えます。;
これは丸めを行いますので、0.009
となります0.01
。カット呼び出しの代わりに使用しますint($(NF-2)*100)/100)
。$(NF-2)
sprintf()
表現sed
にバックスラッシュが多すぎます。特に、キャプチャグループを終了する必要がある拡張正規表現でwhichを使用し、\)
重要な角括弧式を無効にするためにwhichを使用し、代わりに不要な部分を使用しました。)
\[
[
\;
;
標準sed
用語で表現すると、次のようになります。
s/\(\.[0-9]\)\(\(;[^;]*\)\{2\}\)$/\10\2/
s/\(\.[0-9][0-9]\)[0-9]\{1,\}\(\(;[^;]*\)\{2\}\)$/\1\2/
拡張正規表現と同じです(現在は次のように使用するための非標準ですsed -E
。 )
s/(\.[0-9])((;[^;]*){2})$/\10\2/
s/(\.[0-9][0-9])[0-9]+((;[^;]*){2})$/\1\2/
これは、変更したフィールドの後の最後の2つのフィールドと明示的に一致するため、式よりも安全です。したがって、誤って任意の浮動小数点値を変更するリスクが少なくなります。