2017-03-01 79 views
0

我需要从日志文件中提取条目并将它们放在错误文件中。在grep -q上使用变量不会生成结果

我不想要复制的误差项文件中的每个脚本运行的时间,所以我创造这样的:

grep $1 $2 | while read -r line ; do 
    echo "$line" 
    if [ ! -z "$line" ] 
    then 
      echo "Line is NOT empty" 
      if grep -q "$line" $3; then 
        echo "Line NOT added" 
      else 
        echo $line >> $3 
        echo "Line added" 
      fi 
    fi 
done 

,并使用运行:

./log_monitor.sh ERROR logfile.log errors.txt 

的第一次脚本运行时会查找条目,并创建错误文件(以前没有错误文件)。

下一次,该行从来没有发现最近添加的行中的错误文件,

如果grep的-q “$行” $ 3;

因此,该脚本将相同的条目添加到错误文件中。

为什么会发生这种情况的任何想法?

+0

顺便说一句,'set -x'是你的朋友 - 你遗漏的引号很可能是相应的。如果你的行在任何时候都有一个或两个空格,'echo $ line'会将它们改变为一个空格,而'echo'$ line“'会忠实地代表它们。 –

回答

3

这很可能是因为您不是在搜索该行本身,而是将该行视为正则表达式。比方说,你有这样的文件:

$ cat file 
[ERROR] This is a test 
O This is a test 

,并尝试找到的第一行:

$ grep "[ERROR] This is a test" file 
O This is a test 

正如你所看到的,它不符合我们正在寻找(导致重复)行并匹配不同的行(导致删除的条目)。您可以改用-F -x搜索匹配的全行文字字符串:

$ grep -F -x "[ERROR] This is a test" file 
[ERROR] This is a test 

应用给你的脚本:

grep -e "$1" -- "$2" | while IFS= read -r line ; do 
    printf '%s\n' "$line" 
    if [ "$line" ] 
    then 
      echo "Line is NOT empty" 
      if grep -Fxq -e "$line" -- "$3"; then 
        echo "Line NOT added" 
      else 
        printf '%s\n' "$line" >> "$3" 
        echo "Line added" 
      fi 
    fi 
done 

grep $1 $2 | while read -r line ; do 
    echo "$line" 
    if [ ! -z "$line" ] 
    then 
      echo "Line is NOT empty" 
      if grep -F -x -q "$line" $3; then 
        echo "Line NOT added" 
      else 
        echo $line >> $3 
        echo "Line added" 
      fi 
    fi 
done 
额外的修复和清理

这里PS:这可能会更短,更快,并具有更好的时间复杂度,其代码片段为awk

+0

谢谢你,你的固定和清理代码是胜利者。看来问题是将行保存到错误中。文本;回声以与printf不同的方式进行。第一个例子(使用我的回声)不起作用,但使用printf和\ n完美工作。再次感谢你! –

+0

@SantiagoMartinez,*点头* - 参见[回声的POSIX标准](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html),它详细描述了实现如何变化和明确建议使用'printf'代替新开发。 –

+0

该修复程序不像引用变量那样使用'printf'。如果你的行包含全局字符('[] *?'),制表符,行中的多个空格或类似行,这将导致[回写写其他东西](http://stackoverflow.com/questions/29378566/i-刚刚分配 - 一个变量,但是回波值变量显示出头,其他)。 –

0

有没有必要检查空白行;第一个grep只检查带有“ERROR”这个词的文字,该文字不能为空。

如果你没有诊断echo消息做,几乎全是代码的归结什么可能使用两个grep s内完成,一个bashprocess substitutionsponge,并且touch的首轮情况:

[ ! -f $3 ] && touch $3 ; grep -vf $3 <(grep $1 $2) | sponge -a $3