转换 shell 脚本中时间跨度的文本表示

转换 shell 脚本中时间跨度的文本表示

我有一个程序可以输出以下格式的时间

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

请注意,在算术运算中处理秒+纳秒值时,通常需要任意精度(此处使用bignumin ),例如在操作中,如果您想将精度保留到纳秒,因为您的处理器/C 编译器通常使用的类型进行算术运算的工具(、without 、 shell...)没有足够的精度。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}'

这将使用 ors作为ns字段分隔符(多字符字段分隔符将被解释为正则表达式,而不仅仅是多字符字符串),并使用.as 分隔符打印字段一和字段二(后者现在用零填充到 9 位小数) 。

所以在你的脚本中,你可以使用

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

相关内容