awk“日期” | getline var缓存其值-但仅在某些情况下

罗伊马

作为较大awk脚本的一部分,我需要将自日期起的任意日期字符串转换为秒。这不能作为awk函数使用,所以我认为我可以重新安排date在输入的每一行上进行调用(事后看来,我本可以使用perl,但让我们停下来思考。)

看到一些意外的结果后,我将问题简化为这个问题(bash和GNU awk

for f in {1..5}; do echo $f; sleep 2; done | awk '{ "date" | getline x; printf ">>%s<<\n", x }'

即使我确认awk循环实际上每两秒运行一次,结果也一样

>>29 Jun 2020 10:38:24<<
>>29 Jun 2020 10:38:24<<
>>29 Jun 2020 10:38:24<<
>>29 Jun 2020 10:38:24<<
>>29 Jun 2020 10:38:24<<

也许getline缓存。所以我尝试了这个

for f in {1..5}; do echo $f; sleep 2; done | awk '{ "date; : " NR | getline x; printf ">>NR=%d - %s<<\n", NR, x }'

>>NR=1 - 29 Jun 2020 10:44:05<<
>>NR=2 - 29 Jun 2020 10:44:07<<
>>NR=3 - 29 Jun 2020 10:44:09<<
>>NR=4 - 29 Jun 2020 10:44:11<<
>>NR=5 - 29 Jun 2020 10:44:13<<

一切似乎都很好。禁用了缓存(如果就是这样),并且我从获得了期望的值date

然后,我再一次沿着这条路径继续,在通过管道传递给以下命令的命令中提供了重复的值 getline

for f in 1 2 1 1 2 3; do echo $f; sleep 2; done | awk '{ "date; : " $1 | getline x; printf ">>NR=%d - f=%d - %s<<\n", NR, $1, x }'

>>NR=1 - f=1 - 29 Jun 2020 10:43:01<<
>>NR=2 - f=2 - 29 Jun 2020 10:43:03<<
>>NR=3 - f=1 - 29 Jun 2020 10:43:03<<
>>NR=4 - f=1 - 29 Jun 2020 10:43:03<<
>>NR=5 - f=2 - 29 Jun 2020 10:43:03<<
>>NR=6 - f=3 - 29 Jun 2020 10:43:11<<

我希望第3行会导致对该命令进行新的评估(传递新的日期值),或者从第一行重复该值。都没有发生。

这让我难过。我不明白为什么我要在第2-5行获得相同的值。f更改12明显禁用正在发生的任何缓存。但是f2返回更改1并没有给我第一个的缓存副本f=1,而是重复了的值f=2通过f=3触发对的新调用将命令字符串更改为新值date

为什么?

伊尔卡楚

GNU awk的手册中提到

如果在执行awk程序期间多次将相同的文件名或相同的shell命令与getline一起使用(请参见使用getline的显式输入部分),则仅第一次打开(或执行命令)文件。那时,从该文件或命令中读取输入的第一条记录。下次将同一文件或命令与getline一起使用时,将从中读取另一个记录,依此类推。

因此,它仅运行一次命令,并且在进一步读取时会得到EOF,而保留旧值x不变。比较一下,如果我们x在每次读取后都进行垃圾回收会发生什么情况

$ for f in {1..3}; do echo $f; sleep 2; done |
   awk '{ "date" | getline x; printf ">>%s<<\n", x; x ="done" }'
>>Mon Jun 29 13:37:53 EEST 2020<<
>>done<<
>>done<<

如果我们在date此处用记录运行时间命令替换该命令,那么我们还可以看到该记录显示该命令仅执行一次。

getline 确实也会在EOF处返回零,并在错误处返回-1,因此我们可以检查一下:

$ for f in {1..3}; do echo $f; sleep 2; done |
    awk '{ if ("date" | getline x > 0) printf ">>%s<<\n", x; else printf "error or eof\n"; }'
>>Mon Jun 29 13:46:58 EEST 2020<<
error or eof
error or eof

您需要close()显式地管道,以在下一次重新打开awk。

$ for f in {1..3}; do echo $f; sleep 2; done |
   awk '{ "date" | getline x; printf ">>%s<<\n", x; x = "done"; close("date") }'
>>Mon Jun 29 13:39:19 EEST 2020<<
>>Mon Jun 29 13:39:21 EEST 2020<<
>>Mon Jun 29 13:39:23 EEST 2020<<

使用"date; : " NR | getline x;,所有命令行都是不同的,因此每个命令行都有一个单独的管道。

使用"date; : " $1 | getline x;,当$1重复时,您会遇到与第一种情况相同的问题,第二遍读到相同管道的结果将到达EOF。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Laravel 7 DB查询仅在日期范围不在日期范围内的情况下

在某些情况下,shell日期“ -n hours”与“ n hours ago”不同

如何在不阻塞输入的情况下使用getline?

仅在定义了值的情况下向对象添加属性

在忽略某些值的情况下计算模式

仅在没有日期和时间冲突的情况下保存新实体(播放)

从指定日期回溯7天,仅在存在该天的情况下才检索值

仅在列包含值的情况下使用SUBTOTAL

在某些情况下如何修改委托以设置其返回值的属性

MySQL-查找唯一值,但仅在某些变量为true的情况下

在不知道AWK中确切位置的情况下替换缺失值

Python Selenium如何仅在锚标记包含某些属性值的情况下获取锚标记href值

jQuery仅在没有缓存的情况下预加载图像

awk命令中的getline安全使用吗?

getline,awk和日期(格式化日期)

使用getline和awk的奇怪行为

是否可以在不加载RavenDB文档的情况下找出其最后更新日期?

在某些情况下如何sed,awk或tr某些字符?

“ getline”如何在AWK中工作?

使用DocBlocks-如何指示函数仅在某些情况下返回值?

在某些情况下无法获取表单ID的值

Excel日期错误:Excel无法识别为日期;使用Date =函数会增加2年,但仅在某些情况下

仅在修改某些单元格的情况下,才如何更新单元格中的日期

AWK getline 问题

在没有 getline 的情况下,在 C++ 中读取字符串直到换行

在某些情况下,Javascript 在执行 .setDate(currentDate.getDate() - 30) 时获取日期错误

在某些情况下它没有任何值时,“到期日期”列类型应该是什么?(空白?空?0000-00-00?)

Jmeter正则表达式仅在日期值为空的情况下捕获默认日期值

C++ 程序在不运行某些行的情况下以某些返回值退出?