如何向shell中的查询提供文本文件的输入

如何向shell中的查询提供文本文件的输入,shell,grep,Shell,Grep,我在写一个shell脚本,却被困在了一个地方。我有一个输入文件,其中有两列,第一列有一个日志文件名,第二列有语法第一次出现的行号。示例如下 文件名:checkit.txt 内容 hellohowru.log 12345 helpmehere.log 45677 checkitout.log 67543 我想在txt文件checkit.txt中的每个日志文件中从相应行的行号开始搜索特定的语法或单词 如何对所有日志文件进行循环 例如:tail-n+12345 hellohowru.log | gr

我在写一个shell脚本,却被困在了一个地方。我有一个输入文件,其中有两列,第一列有一个日志文件名,第二列有语法第一次出现的行号。示例如下

文件名:checkit.txt

内容

hellohowru.log 12345
helpmehere.log 45677
checkitout.log 67543
我想在txt文件checkit.txt中的每个日志文件中从相应行的行号开始搜索特定的语法或单词

如何对所有日志文件进行循环

例如:
tail-n+12345 hellohowru.log | grep-il“exception”
如果发现异常,我可以得到文件名


请帮助

您可以在阅读循环时在
中执行此操作:

while read -r file num; do
    tail -n +$num "$file" | grep -qi 'exception' && echo "$file"
done < checkit.txt > output.txt
while read-r file num;做
tail-n+$num“$file”| grep-qi“异常”和&echo“$file”
完成output.txt
上面使用GNU awk来处理
nextfile
和任意数量的打开文件-如果您没有gawk,那么在任何awk中它将是:

awk '
    NR==FNR { ARGV[ARGC]=$1; ARGC++; start[$1]=$2; next }
    FNR==1  { close(prev); prev=FILENAME }
    (FNR > start[FILENAME]) && (tolower($0) ~ /exception/) && !seen[FILENAME]++ { print FILENAME }
' checkit.txt

另一个简单的解决方案

算法:
-逐行读取文件
-获取文件名和行名
-对“异常”执行tail+grep命令
-如果找到匹配项,请打印文件名

cat checkit.txt | while read line
do
    LOGFILE=$(echo $line | awk -F ' ' '{print $1}')
    LINECNT=$(echo $line | awk -F ' ' '{print $2}')
    #echo "HI : $LOGFILE and $LINECNT"

    tail -n +$LINECNT $LOGFILE | grep -i "exception" 1> /dev/null
    if [ $? -eq 0  ]
    then
        echo "EXCEPTION IN $LOGFILE"
    fi
done

该脚本中至少有六个shell脚本错误。如果您想了解它们,请告诉我。一目了然:1)UUOC 2)读取时不正确的
语法3)对非导出变量使用大写名称4)不必要地将awk FS设置为其默认值。5) 不引用shell变量6)grep输出重定向上的错误文件描述符7)重定向grep输出,而不是使用grep arg不生成输出。8) 阅读整行然后拆分,而不是在阅读时拆分。让我知道,如果有任何这些你不明白,并希望更多的信息。谢谢你的答复。我应该小心。顺便说一句(6,7)是故意的:我不想打印o/p,因为用户没有要求它。我不理解UOOC;我的错。而且我也不明白为什么
阅读时语法不正确?对于6,我应该说“不必要”而不是“错误”,因为
1
cmd>任何东西的默认FD。对于7,只需使用
grep-q
,它就不会产生输出,不需要让grep产生输出,然后将其重定向到/dev/null。UUOC的意思是“无用地使用Cat”,这与不引用变量一起是迄今为止最常见的shell脚本错误。谷歌UOOC。当您想按原样从文件中读取行时,需要使用
,而IFS=read-r line
。否则,您在变量中得到的内容可能与文件中的内容不同,因此,只有在实现目标的必要时才谨慎行事。不客气。请参阅@anubhava的答案,了解如何在shell中编写它而不出现我列出的问题1、2、3、5、7和8(4和6不适用于他的脚本,因为解决7和8就不需要出现这些问题的行)。shell不是设计用来操作文本的,它是设计用来操作文件、进程和对工具的顺序调用的——这就是为什么要正确地编写shell脚本来操作文本是如此困难的原因。对于文本操作,只需使用awk—它就是为它而设计的,因此操作简单、直观、高效(比shell循环快得多!)
cat checkit.txt | while read line
do
    LOGFILE=$(echo $line | awk -F ' ' '{print $1}')
    LINECNT=$(echo $line | awk -F ' ' '{print $2}')
    #echo "HI : $LOGFILE and $LINECNT"

    tail -n +$LINECNT $LOGFILE | grep -i "exception" 1> /dev/null
    if [ $? -eq 0  ]
    then
        echo "EXCEPTION IN $LOGFILE"
    fi
done