使用awk匹配日志文件中的一列并打印整行



我正在尝试编写一个脚本来分析日志文件,我想让用户可以选择输入一个模式,然后在特定的列(第五列)中打印任何与该模式匹配的行终端的以下工作

awk ' $5=="acpid:" {print$0}' *filename*

好的,所以上面我试图匹配"acpid:"这很好,但在脚本中,我希望能够允许多个条目并搜索所有条目,问题是我把脚本中的变量搞砸了,这就是我所拥有的:

echo "enter any services you want details on, seperated by spaces"
read -a details
for i in ${details[@]}    
do 
echo $i
awk '$5 == "${i}" {print $0}' ${FILE}
done

同样,如果我直接输入一个匹配的表达式,而不是变量,它会起作用,所以我想我的问题是这里,任何提示都是很棒的

更新

因此,我使用@ghoti建议的第二个选项(如下所示),因为它与我的日志文件匹配得稍微好一些然而,我没有任何运气与多个条目。我添加了两行来说明我得到的结果,这两行是echo$i和echo"finish loop",它们应该告诉我循环当前的输入和我离开循环

'read -a details
re=""
for i in "${details[@]}"; do
re="$re${re:+|}$i"
echo $i
echo"finish loop"
done
awk -v re="$re" '$5 ~ re' "$FILE" `

当我分别给read一个"acpid"或"init"的输入时,完美的结果是匹配的,然而当输入是"acpid init"时,下面是输出

acpid初始化
完成循环

我从中看到的是,read将两个单词作为一个条目,然后awk正在搜索,但没有匹配它们(正如预期的那样)。那么,为什么输入没有被视为两个独立的条目呢?我曾认为,带有read的-a选项指定了用空格分隔的单词将被放入数组的独立元素中。也许我没有正确声明数组?

更新

好吧,取消上面的更新,就像我愚弄了我一样,我忘记了我在脚本的早些时候把IFS改回来了!!!

再次感谢@ghoti的帮助!!

有几种方法可以随心所欲。

一种选择可能是为每个单词运行一个for循环,然后对awk应用不同的调用,并按顺序显示结果。例如,如果在$details变量中输入foo bar,则可能会得到一个foo匹配项列表,然后是bar匹配项列表:

read -a details
for i in "${details[@]}"; do
awk -v s="$i" '$5 == s' "$FILE"
done

这里的想法是,我们使用awk的-v选项将每个单词放入脚本中,而不是在引用的脚本中扩展变量。您应该阅读bash如何处理不同类型的引号。(这里、这里和其他地方也有一些关于堆栈溢出的问题。)

另一种选择可能是构造一个正则表达式,同时搜索您感兴趣的所有单词。这样做的好处是使用awk的单次运行来搜索$FILE:

read -a details
re=""
for i in "${details[@]}"; do
re="$re${re:+|}$i"
done
awk -v re="$re" '$5 ~ re' "$FILE"

结果将包含$FILE中所有感兴趣的行,按它们在$FILE中出现的顺序排列,而不是按您提供的单词排列。

注意,这是一个相当初级的搜索,没有单词边界,所以如果你搜索"foo-barbabar",你可能会得到你不想要的结果。不过,您可以自己使用regex。:)

这能回答你的问题吗?

相关内容

  • 没有找到相关文章

最新更新