Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
查找以毫秒为单位的时差awk或gawk_Awk - Fatal编程技术网

查找以毫秒为单位的时差awk或gawk

查找以毫秒为单位的时差awk或gawk,awk,Awk,我将包含大量数据的文件转换为以下格式,我想找出以毫秒为单位的两个时间戳之间的差异,并在最后添加一列,显示该行的时间差异 22159 | a | 2021-02-26 11:02:03.776 | 2021-02-26 11:02:04.740 22160 | b | 2021-02-26 11:35:21.796 | 2021-02-26 11:35:22.674 22161 | c | 2021-02-26 11:35:21.806 | 2021-02-26 11:35:22.841 2216

我将包含大量数据的文件转换为以下格式,我想找出以毫秒为单位的两个时间戳之间的差异,并在最后添加一列,显示该行的时间差异

22159 | a | 2021-02-26 11:02:03.776 | 2021-02-26 11:02:04.740
22160 | b | 2021-02-26 11:35:21.796 | 2021-02-26 11:35:22.674
22161 | c | 2021-02-26 11:35:21.806 | 2021-02-26 11:35:22.841
22161 | d | 2021-02-26 11:02:18.688 | 2021-02-26 11:02:19.594
22182 | e | 2021-02-26 11:06:02.978 | 2021-02-26 11:06:03.815
22183 | f | 2021-02-26 11:35:24.911 | 2021-02-26 11:35:25.791
22184 | g | 2021-02-26 11:35:25.082 | 2021-02-26 11:35:26.121
22199 | h | 2021-02-26 11:09:47.815 | 2021-02-26 11:09:48.499
22200 | i | 2021-02-26 11:35:27.562 | 2021-02-26 11:35:28.660
22200 | j | 2021-02-26 11:09:49.595 | 2021-02-26 11:09:50.596
输出,输出

9535a 2021-02-27 11:02:53.756 2021-02-27 11:02:53.947 0.191

我的命令如下:

awk -F'|' 'function convert(t) {   cmd = "date +%s.%3N -d \""t"\" "; cmd|getline timemilli; return timemilli; } { t2=convert($4);t1=convert($3);printf $1"\t"$2"\t"$3"\t"$4"\t%.3f\n",t2-t1 }' filtered_data
它的工作很好的小文件,但它给了我错误的大文件

错误:

awk:cmd。第1行:(FILENAME=filtered_data FNR=516)致命:无法打开管道date+%s.%3N-d“2021-02-27 11:24:05.618”(打开的文件太多)`

注意:我的文件大约是10MB,我想找出单个快照中的差异。不在每条线上循环


在单次拍摄中还有其他方法吗?

使用GNU awk,因为
mktime()
gensub()

输出:

22159 a 2021-02-26 11:02:03.776 2021-02-26 11:02:04.740 -0.964
22160 b 2021-02-26 11:35:21.796 2021-02-26 11:35:22.674 -0.878
22161 c 2021-02-26 11:35:21.806 2021-02-26 11:35:22.841 -1.035
...

注意:
mktime()
需要时间,格式为
“YYYY-MM-DD-HH-MM-SS[DST]”
。上面我正在滥用(由于懒惰)并以
格式“YYYY-MM-DD-HH-MM-SS-sss”
将其输入,其中
sss
是毫秒。它似乎可以工作,但您可能需要使用例如
substr()
或类似的工具来解决此问题。

使用GNU awk,因为
mktime()
gensub()

输出:

22159 a 2021-02-26 11:02:03.776 2021-02-26 11:02:04.740 -0.964
22160 b 2021-02-26 11:35:21.796 2021-02-26 11:35:22.674 -0.878
22161 c 2021-02-26 11:35:21.806 2021-02-26 11:35:22.841 -1.035
...

注意:
mktime()
需要时间,格式为
“YYYY-MM-DD-HH-MM-SS[DST]”
。上面我正在滥用(由于懒惰)并以
格式“YYYY-MM-DD-HH-MM-SS-sss”
将其输入,其中
sss
是毫秒。它似乎可以工作,但您可能需要使用例如
substr()
或类似的工具来修复此问题。

您可以尝试此
awk

awk-F'|''
函数转换(t、cmd、timemilli){
cmd=“日期+%s.%3N-d\”“t”
cmd | getline timemilli
关闭(cmd)#关闭此cmd以避免打开过多文件
返回时间毫秒
}
{
t2=转换(4美元)
t1=转换(3美元)
打印文件“%s\t%.3f\n”,“1”\t“$2”\t“$3”\t“$4,t2-t1
}“过滤的数据”

您可以试试这个
awk

awk-F'|''
函数转换(t、cmd、timemilli){
cmd=“日期+%s.%3N-d\”“t”
cmd | getline timemilli
关闭(cmd)#关闭此cmd以避免打开过多文件
返回时间毫秒
}
{
t2=转换(4美元)
t1=转换(3美元)
打印文件“%s\t%.3f\n”,“1”\t“$2”\t“$3”\t“$4,t2-t1
}“过滤的数据”

用于
mawk
1.3.4。参见
mktime
上的mawk文档了解 夏令时
dst

LC_ALL=C awk -v FS=' +\| ' -v OFS='|' -v RS=' <br/>\n' -v OFMT='%.3f' -v dst='-1' '
function fn(s) {
    # return epoch seconds, with milliseconds as fraction
    gsub(/-|:/," ",s)
    return mktime(substr(s,1,19) " " dst) + substr(s,21,3)/1000
}{ $(NF+1) = fn($4) - fn($3) }
1
' data
LC\u ALL=C awk-vfs='+\\\\'-vofs=''\\\\'-vrs='
\n'-vofmt='%.3f'-vdst='-1'' 功能fn(s){ #返回以毫秒为分数的历元秒数 gsub(/-:/,“”,s) 返回mktime(substr(s,1,19)”“dst)+substr(s,21,3)/1000 }{$(NF+1)=fn($4)-fn($3)} 1. "数据,

EDIT编辑
FS
RS
以匹配OP的新输入格式。

用于
mawk
1.3.4。参见
mktime
上的mawk文档了解 夏令时
dst

LC_ALL=C awk -v FS=' +\| ' -v OFS='|' -v RS=' <br/>\n' -v OFMT='%.3f' -v dst='-1' '
function fn(s) {
    # return epoch seconds, with milliseconds as fraction
    gsub(/-|:/," ",s)
    return mktime(substr(s,1,19) " " dst) + substr(s,21,3)/1000
}{ $(NF+1) = fn($4) - fn($3) }
1
' data
LC\u ALL=C awk-vfs='+\\\\'-vofs=''\\\\'-vrs='
\n'-vofmt='%.3f'-vdst='-1'' 功能fn(s){ #返回以毫秒为分数的历元秒数 gsub(/-:/,“”,s) 返回mktime(substr(s,1,19)”“dst)+substr(s,21,3)/1000 }{$(NF+1)=fn($4)-fn($3)} 1. "数据,

EDIT编辑了
FS
RS
,以匹配OP的新输入格式。

错误消息似乎表明有多个打开的文件,但您只有一个非常大的文件,对吗?是的。我只打开一个文件。对于某些条目,它似乎给出了错误的差异:775875 a 2021-02-27 12:01:44.231 2021-02-27 12:01:44.454 0.000我认为错误消息与使用了许多不带。请参阅@anubhava的答案。当您使用GNU特定选项(
-d
%N
)时,显然您有GNU日期,因此您必须也有GNU awk可用,但当您有太多打开的输出文件或管道时,GNU awk不会失败,它只会减慢速度,因此尽管它可用,但您不会调用它。因此,只要调用GNU awk而不是您正在调用的任何awk,就可以避免该错误,但是如果你有GNU awk,有一个更好的方法来做你想做的事情,那就是使用它的内置时间函数,而不是在每个输入行生成一个子shell来调用
date
两次。在少数情况下,调用
getline
是正确的方法,您应该在使用仅在成功时才填充的变量之前测试其成功/失败结果,有关详细信息,请参阅。错误消息似乎表明有多个打开的文件,但您只有一个真正大的文件,对吗?是的。我只打开一个文件。对于某些条目,它似乎给出了错误的差异:775875 a 2021-02-27 12:01:44.231 2021-02-27 12:01:44.454 0.000我认为错误消息与使用了许多不带。请参阅@anubhava的答案。当您使用GNU特定选项(
-d
%N
)时,您显然有GNU日期,因此您也必须有GNU awk可用,但GNU awk不会fai