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

问题描述 投票:0回答:1

目标:我想对下面代码中显示的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" ) 

linux bash while-loop grep
1个回答
0
投票

您的问题在这里:

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

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

问题:尽管tail命令和while循环正在运行,但随着数据线的进入,似乎没有任何模式匹配。

你怎么知道?很多时候,使用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选项为您<< c >>包围线。将整个内容包装在命令替换中,以将其设置为cnt变量:cnt=$(tail -f --pid=$$ ${1:-access.log} | grep -c --line-buffered "20")

© www.soinside.com 2019 - 2024. All rights reserved.