「e」なしで科学フォーマットを操作する


8

科学表記法で数値を含むファイルを操作しようとしていますが、e記号はありません。つまり、1.2e+3と書かれてい1.2+3ます。

私がやって考える最も簡単な方法は、awk交換した+e+使用して、gsub機能を新しいファイルで私の計算を行います。マイナスの場合も同様です。したがって、次のコマンドを使用して簡単な修正を行うことができます

awk '{gsub("+", "e+", $1); print $1, $2, $3, $4, $5}' file_in

すべての列で同じことを行います。

ただし、ファイルには負の値も含まれているため、少し複雑になります。サンプルファイルは次のとおりです。

 1.056000+0 5.000000-1 2.454400-3 2.914800-2 8.141500-6
 2.043430+1 5.000000-1 2.750500-3 2.698100-2-2.034300-4
 3.829842+1 5.000000-1 1.969923-2 2.211364-2 9.499900-6
 4.168521+1 5.000000-1 1.601262-2 3.030919-2-3.372000-6
 6.661784+1 5.000000-1 5.250575-2 3.443669-2 2.585500-5
 7.278104+1 5.000000-1 2.137055-2 2.601701-2 8.999800-5
 9.077287+1 5.000000-1 1.320498-2 2.961020-2-1.011600-5
 9.248130+1 5.000000-1 3.069610-3 2.786329-2-6.317000-5
 1.049935+2 5.000000-1 4.218794-2 3.321955-2-5.097000-6
 1.216283+2 5.000000-1 1.432105-2 3.077165-2 4.300300-5

このようなファイルを操作および計算する方法についてのアイデアはありますか?


2
どのように2.698100e-2-2.034300e-4のような形式で計算しますか?
ctac_

3
これは、おそらく固定幅の列データとして解析されることを意図しているようです。列間の見かけ上の空白は、プラス記号の代わりに先行スペースを持つ正の値を表示する数値フォーマットの単なるアーティファクトです。
Ilmari Karonen

回答:


14

この出力は正しいですか?

 1.056000e+0 5.000000e-1 2.454400e-3 2.914800e-2 8.141500e-6
 2.043430e+1 5.000000e-1 2.750500e-3 2.698100e-2-2.034300e-4
 3.829842e+1 5.000000e-1 1.969923e-2 2.211364e-2 9.499900e-6
 4.168521e+1 5.000000e-1 1.601262e-2 3.030919e-2-3.372000e-6
 6.661784e+1 5.000000e-1 5.250575e-2 3.443669e-2 2.585500e-5
 7.278104e+1 5.000000e-1 2.137055e-2 2.601701e-2 8.999800e-5
 9.077287e+1 5.000000e-1 1.320498e-2 2.961020e-2-1.011600e-5
 9.248130e+1 5.000000e-1 3.069610e-3 2.786329e-2-6.317000e-5
 1.049935e+2 5.000000e-1 4.218794e-2 3.321955e-2-5.097000e-6
 1.216283e+2 5.000000e-1 1.432105e-2 3.077165e-2 4.300300e-5

コード:

perl -lne 's/(\.\d+)(\+|\-)/\1e\2/g; print' sample

説明:

  • -lne 行末の処理、各入力行の処理、次のコードの実行

  • s/(\.\d+)(\+|\-)/\1e\2/g

    • 代用(s
    • (.\d+)(\+|\-) (ドットと数字)と(プラスまたはマイナス)の2つのグループを見つける
    • \1e\2それらを最初のグループで置き換えてeから、2番目のグループで置き換えます
    • g グローバルに-各行の最初の置換で停止せず、可能なすべてのヒットを処理します
  • print 行を印刷する

  • sample 入力ファイル

欠けている場合、これはスペースを追加します。実際、それは関係なく数字の間にスペースを入れます。すなわち。場合によっては2つのスペースがあったとしても、出力には1つしかありません。

perl -lne 's/(\.\d+)(\+|\-)(\d+)(\s*)/\1e\2\3 /g; print' sample

そのほとんどは前のものと似ています。新しいものは(\d+)グループnr 3と(\s*)グループnr 4 *です。ここではオプションを意味します。置換ではno \4が使用されます。代わりにスペースがあります。

出力は次のとおりです。

 1.056000e+0 5.000000e-1 2.454400e-3 2.914800e-2 8.141500e-6 
 2.043430e+1 5.000000e-1 2.750500e-3 2.698100e-2 -2.034300e-4 
 3.829842e+1 5.000000e-1 1.969923e-2 2.211364e-2 9.499900e-6 
 4.168521e+1 5.000000e-1 1.601262e-2 3.030919e-2 -3.372000e-6 
 6.661784e+1 5.000000e-1 5.250575e-2 3.443669e-2 2.585500e-5 
 7.278104e+1 5.000000e-1 2.137055e-2 2.601701e-2 8.999800e-5 
 9.077287e+1 5.000000e-1 1.320498e-2 2.961020e-2 -1.011600e-5 
 9.248130e+1 5.000000e-1 3.069610e-3 2.786329e-2 -6.317000e-5 
 1.049935e+2 5.000000e-1 4.218794e-2 3.321955e-2 -5.097000e-6 
 1.216283e+2 5.000000e-1 1.432105e-2 3.077165e-2 4.300300e-5 

答えてくれてありがとう!はい、それは正しいようです!! 今後の参考のために、あなたが何をしたか説明できますか?
Thanos

最後の列($ 5 $)を前の列からスペースで区切ることもできますか?
Thanos

あなたは完璧です!手伝ってくれてありがとうございます!
Thanos

@Thanos更新を参照してください。また.、最初のグループで前にバックスラッシュを追加したことに注意してください。これは正しいです。このバックスラッシュがなければ、ドットは文字通りのドットを意味しません。

2

を使用することもできますsed。例:

<infile sed -E 's/([0-9])([+-])([0-9])/\1e\2\3/g' | awk '{ print $1 + 0 }'

ただし、これはOPのリストの列が分離されていない場合があることを考慮していません。適切な精度での回避策は次のとおりです。

<infile sed -E 's/.{11}/& /g'       |
sed -E 's/([0-9])([+-])/\1e\2/g'    |
gawk '{ print $1 + 0 }' OFMT='%.7g'

出力:

1.056
20.4343
38.29842
41.68521
66.61784
72.78104
90.77287
92.4813
104.9935
121.6283

これは、番号から解像度を削除し、私は負の値は、問題の例のように、別の隣にあるとき、必ずそれが動作するわけではないんだ2.698100-2-2.034300-4
パイプ

@pipe:あなたは正しい、私はその詳細を逃した。スペースを追加することで回避策を追加しました。に関して。精度、私が使用しOFMTた入力のと同じに設定AWKの精度に変数を
トール
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.