1

我有一个运行两个命令的脚本。第一个命令是将数据写入临时文件。第二个命令是管道到 awk,而第一个命令在后台运行。在第二个命令中,awk 需要从临时文件中读取数据,但它解析自己的数据的速度比将数据写入临时文件的速度要快。

这是一个例子:

#!/bin/bash

command1 > /tmp/data.txt &
# command1 takes several minutes to run, so start command 2 while it runs in the background
command2 | awk '
    /SEARCH/ {
        #Matched input so pull next line from temp file
        getline temp_line < "/tmp/data.txt"
    }
'

这行得通,除非 awk 如此快地解析来自 command2 的数据,以至于 command1 跟不上它。即 awk 在 command1 完成写入之前从 /tmp/data.txt 获取 EOF。

我还尝试在 getline 周围进行一些检查,例如:

while ((getline temp_line < "/tmp/data.txt") < 0) {
    system("sleep 1") # let command1 write more to the temp file
}
# Keep processing now that we have read the next line

但我认为一旦它在临时文件中遇到 EOF,它就会停止尝试从中读取。或类似的东西。

只要 command1 写入临时文件的速度快于 awk 尝试从中读取的速度,整个脚本就可以工作。如果我在两个命令之间放置一个 sleep 10 命令,那么临时文件会构建足够的缓冲区,并且脚本会生成我需要的输出。但是我可能正在解析比我测试过的文件大得多的文件,或者命令可能在不同的系统上以不同的速度运行,等等,所以我想要一个安全机制来等待文件,直到数据被写入它.

任何想法我怎么能做到这一点?

4

1 回答 1

1

我认为您需要在迭代之间关闭文件并从头开始再次将其读取到您之前读取过的位置,就像这样(未经测试);

sleepTime = 0
while ((getline temp_line < "/tmp/data.txt") <= 0) {
    close("/tmp/data.txt")
    system("sleep " ++sleepTime) # let command1 write more to the temp file
    numLines = 0
    while (++numLines < prevLines) {
        if ( (getline temp_line < "/tmp/data.txt") <= 0 ) {
             print "Aaargghhh, my file is gone!" | "cat>&2"
             exit
        }
    }
}
++prevLines

请注意,我内置了一个变量“sleepTime”,以使您的命令每次通过循环都睡得更久,因此如果您的 tmp 文件需要很长时间才能填满您的第二个命令,则每次迭代都会等待更长的时间。随心所欲地使用或不使用。

在带有 system() 命令的嵌套循环中使用 getline 似乎有点笨拙且容易出错 - 我不禁想到可能有更好的方法,但我不知道我脑子里想的是什么。

于 2013-03-13T01:18:17.833 回答