我有一个程序可以输出以下格式的时间
2s576039936ns
我需要将其转换为以下格式:
2.576039936
我怎样才能在shell脚本中做到这一点?
更新:请注意,该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
in ),例如在操作中,如果您想将精度保留到纳秒,因为您的处理器/C 编译器通常使用的类型进行算术运算的工具(、without 、 shell...)没有足够的精度。perl
struct timespec
clock_gettime()
double
awk
perl
bignum
和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}'
这将使用 ors
作为ns
字段分隔符(多字符字段分隔符将被解释为正则表达式,而不仅仅是多字符字符串),并使用.
as 分隔符打印字段一和字段二(后者现在用零填充到 9 位小数) 。
所以在你的脚本中,你可以使用
t=$( your_command | awk -F'n?s' '{printf "%d.%09d\n",$1,$2}' )