正如您所看到的,我下面的代码很清楚,内部循环似乎可以工作,但是当嵌套在另一个循环下时,它就不行了,(no idea why
)
想法是用a
b
while1 迭代变量并将其交给 while2,while2 等待 log_file 中出现一行以执行 case 语句。
它不适用于实际进程,它是真正的 log_file
#!/bin/bash
bi_log='/var/log/process/process.log'
bi_conf='/etc/process/process.conf'
cat input_file | while
read a b
do
while IFS= read -r line; do
case $line in
"Processing Data ended*"* ) echo "Found" &&
echo $a $b >> $bi_conf
;;
esac
sleep 1
break
done < <(tail -n0 -f $bi_log)
done
看起来内部循环工作正常,但将其嵌套在外部循环下可能会出现问题。变量a
&b
不会回显到文件中。
答案1
您的脚本存在几个问题,首先是tail -n0 -f $bi_log
永远不会退出,因此外循环永远不会到达 的第二行input_file
。
尝试更多类似这样的事情:
while read -r a b ; do
tail -n0 -f "$bi_log" |
awk -v a="$a" -v b="$b" \
'/Processing Data ended/ {
print "found" > /dev/stderr;
print a, b ;
exit
}' >> "$bi_conf"
done < input_file
这里 awk 脚本打印其输出并在找到匹配项后立即退出。这将终止tail -n0 -f
管道和 shell,同时循环移动到下一行input_file
(并启动一个新tail | awk
管道)。
顺便说一句,这-v a="$a" -v b="$b"
就是将 shell 变量传递$a
给awk变量a
和 shell 变量$b
转换为 awk 变量b
。或者,您可以export a b
在 shell 中(以便将它们导出到子进程可见的环境中),然后在 awk 中使用ENVIRON["a"]
and 。ENVIRON["b"]
input_file
如果我对和a
和变量了解更多b
,那么整个事情很可能可以在 中完成awk
。或者perl
。
或者,您可以仅使用bash
和来完成此操作grep
。例如
while read -r a b ; do
tail -n0 -f "$bi_log" | grep -q -m 1 'Processing Data ended'
echo "Found"
echo "$a $b" >> "$bi_conf"
done < input_file
该-m NUM
选项告诉 grep 在匹配后退出NUM
(在本例中,NUM=1)。该-q
选项告诉 grep 保持安静,即不产生任何输出,只返回退出代码(0 表示成功,1 表示失败......但因为 grep 的输入来自tail -f
它将永远继续读取,直到找到匹配项)。
PS:作为一般经验法则,如果您发现自己在 shell 中编写 while/read 循环,您应该停下来思考“我应该在 awk/perl/python/anything-but-shell 中执行此操作”。然后用更合适的语言写出来。
Shell 非常适合协调文本和数据处理工具的执行。它本身的处理很糟糕。
看为什么使用 shell 循环处理文本被认为是不好的做法?了解详细信息和示例。