我有一个运行两个命令的脚本。第一个命令是将数据写入临时文件。当第一个命令在后台运行时,第二个命令是管道到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命令,那么临时文件会构建足够的缓冲区并且脚本会产生我需要的输出。但我可能正在解析比我测试的文件大得多的文件,或者命令可能在不同的系统上以不同的速度运行等等,所以我想要一种安全机制来等待文件,直到数据被写入它
我有什么想法可以做到这一点吗?
答案 0 :(得分: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虽然看起来有点笨拙且容易出错 - 我不禁想到可能有更好的方法,但我不知道我的头脑是什么。< / p>