シェルスクリプトから時間範囲のテキスト表現を変換する

シェルスクリプトから時間範囲のテキスト表現を変換する

次の形式で時間を出力するプログラムがあります。

2s576039936ns

次の形式に変換する必要があります。

2.576039936

シェルスクリプトでこれをどのように実行できますか?

修正する:このnsセクションは9桁の数字で埋められないので、2s513nsこのような出力が出る可能性があるので2.000000513

答え1

2s576039936nsこのソリューションは以下も処理します2s123ns

$ echo 2s576039936ns | tr '[:alpha:]' ' ' | awk -- '{ printf "%d.%09d",$1,$2 }'
2.576039936

$ echo 2s123ns | tr '[:alpha:]' ' ' | awk -- '{ printf "%d.%09d",$1,$2 }'
2.000000123

答え2

Bashのこの機能を使用できます(POSIXかどうかわからない)。

x=2s576039936ns
y=${x/s/.}
z=${y/ns/}
echo $z

またはsed:

echo 2s576039936ns | sed 's/s/./; s/ns//'

どちらの方法も最初に s をドットに変えてから ns を削除します。

まったく異なる場合:

echo 2s576039936ns | awk -F '[ns]' '{print $1 "." $2}'

これはあなたがただ変化を望んでいると仮定します滞在数字ではなく。

答え3

そしてperl

$ echo 10000s12576039936ns 1s1ns 0001s1000000ns 12s0ns |
   perl -Mbignum -pe 's{(\d+)s(\d+)ns}{$1 + $2 / 1e9}ge'
10012.576039936 1.000000001 1.001 12

算術演算で秒+ナノ秒の値を扱う場合は、任意の精度(ここで使用)が必要です。bignumたとえば、プロセッサ/Cコンパイラが精度をナノ秒まで維持したい場合、ツールで一般的に使用されるタイプです。算術演算を実行する(シェルなし...)精度が不十分です。perlstruct timespecclock_gettime()doubleawkperlbignum

そしてzsh

string='10000s12576039936ns 1s1ns 0001s1000000ns 12s0ns'

set -o extendedglob
newstring=${string//(#b)(<->)s(<->)ns/\
$((match[1] + match[2] / 10**9))${${:-.${(l[9][0])match[2]}}%%(.|)0#}}

10012.576039936 1.000000001 1.001 12それも提供します$newstring(ここでは両方の数値に対して整数算術を使用し、このような浮動小数点zshについても使用doubleします)。

答え4

「テキスト表現」だけを変換したいと思うので、コマンドの出力をパイプできますsed。次のコマンドは最初に削除され、次にns置き換えsられます.

~$ echo "2s576039936ns" | sed -e 's/ns//' -e 's/s/./'
2.576039936

修正する

コメントでは、ナノ秒部分は正確に9桁までゼロで埋められないことを指摘しました。この場合、出力が無効になります。この問題を解決するには、次のソリューションを使用できますawk

~$ echo "2s576039936ns" | awk -F'n?s' '{printf "%d.%09d\n",$1,$2}'

sこれはフィールド区切り文字としてまたはを使用しns(マルチキャラクタフィールド区切り文字はマルチ文字列ではなく正規表現として解釈されます)、区切り文字として.フィールド1とフィールド2を印刷します(後者は0から9まで埋められます) 。小数点の桁)。

したがって、スクリプトで次のものを使用できます。

t=$( your_command | awk -F'n?s' '{printf "%d.%09d\n",$1,$2}' )

関連情報