在连续/实时数据流上使用 grep



目标:我想对来自以下代码中提供的tail命令的每一行传入数据进行实时模式匹配。

问题:尽管tail命令和while-loop正常工作,但随着数据行的进入,似乎没有某种模式匹配。

#!/bin/bash
# 
# Description: 
# 
# Usage: 
#
function interval () 
{ 
echo $(date '+%y%m%d %H%M%S') $cnt 
cnt=0 
} 
declare -i cnt=0 
trap interval SIGUSR1
target_file=${1:-access.log) 
shopt -s lastpipe 
tail -f --pid=$$ ${1:-access.log} | grep --line-buffered "20" | while read aline 
do 
let cnt++ 
done < <( grep --line-buffered "20" ) 

您的问题在这里:

tail -f --pid=$$ ${1:-access.log} | grep --line-buffered "20" | while read aline 
do 
let cnt++ 
done < <( grep --line-buffered "20" )

问题:尽管 tail 命令和 while-loop 正常工作,但随着数据行的进入,似乎没有某种模式匹配。

你怎么知道? 很多时候,在 bash 中,找出问题所在的最简单方法是将碎片分开,看看会发生什么。 例如。如果你只运行

tail -f --pid=$$ ${1:-access.log} | grep --line-buffered "20"

您将能够看到传递到 while 循环中的内容。 管道进入 while 循环会将上述命令的输出发送到 while 循环中。 这就是它的输入。 将输入发送到 while 循环的另一种方法是您在此处执行的进程替换:

done < <( grep --line-buffered "20" ) 

进入 while 循环的管道正在提供输入。 这条线也是。 您只应使用这些方法之一。 但是,此行不执行任何操作,因为它本身需要输入。 如果单独运行该命令,您将看到终端挂起等待您的输入。 尝试在终端上自行运行以下命令:

grep --line-buffered "20"

什么都不会发生。 因此,您使用 2 种方法将输入发送到 while 循环中,并且只应使用一种:

tail -f --pid=$$ ${1:-access.log} | grep --line-buffered "20" | while read aline 
do 
let cnt++ 
done

或。。。

while read aline 
do 
let cnt++ 
done < <( tail -f --pid=$$ ${1:-access.log} | grep --line-buffered "20" )

当然,有一种更简单的方法可以完成所有这些操作。 您似乎正在尝试将 cnt 变量设置为输出中的行数。 不要使用循环,而是尝试使用 grep 的 -c选项来为您创建行。 将整个内容包装在命令替换中,以将其设置为 cnt 变量:

cnt=$(tail -f --pid=$$ ${1:-access.log} | grep -c --line-buffered "20")

最新更新