使用awk匹配日志文件中的一列并打印整行 [英] using awk to match a column in log file and print the entire line
问题描述
我正在尝试编写一个脚本来分析日志文件, 我想让用户选择输入模式,然后在特定列(第五行)中打印与该模式匹配的任何行 终端上的以下作品
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" `
当我分别输入"acpid"或"init"的输入时,会匹配一个完美的结果,但是当输入是"acpid init"时,则输出为
acpid初始化
完成循环
我从中看到的是,读取将两个单词作为一个条目,然后awk正在搜索但不匹配它们(这是预期的).因此,为什么不将输入视为两个单独的条目,我曾认为-a选项与read一起指定将由空格分隔的单词放置在数组的单独元素中.也许我没有正确声明数组?
更新更新
好,取消上述更新,就像我傻瓜一样,我忘记了ID将IFS更改为\ n之前的脚本,并将其更改为宾果游戏!
再次感谢@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的 结果将包含 请注意,这是一个非常基本的搜索,没有单词边界,因此,如果搜索"foo bar babar",可能会得到不需要的结果.不过,您可以自己使用正则表达式. :) 这能回答您的问题吗? I'm trying to write a script which will analyse a log file,
i want to give the user the option to enter a pattern and then print any line which matches this pattern in a specific column (the fifth one)
the following works from the terminal ok so above im trying to match "acpid:" this works fine but in the script i want to be able to allow multiple entries and search for them all, the problem is i'm messing up the variable in the script this is what i have: again if i directly put in a matching expression instead of the variable it works so i guess my problem is here any tips would be great UPDATE So im using the second option suggested(shown below) by @ghoti as it matches my log file slightly better
however im not having any luck with multiple entries. ive added two lines to illustratre the results im getting these are echo $i and echo "finish loop" as placed they should tell me what input the loop is currently on and that im leaving the loop When i give read an input of either "acpid" or "init" seperately a perfect result is matched, however when the input is "acpid init" the following is the output acpid init What im seeing from this is that the read is taking the both words as one entry and then the awk is searching but not matching them (as would be expected). so why is the input not being taken as two separate entries i had thought the -a option with read specified that words separated by a space would be placed into separate elements of the array. perhaps i have not declared the array correctly? Update update ok cancel the above update like i fool i'd forgotten that id chaged IFS to \n earlier in the script changed it back and bingo !!! Many thanks again to @ghoti for his help!! There are a few ways that you could do what you want. One option might be to run through a The idea here is that we use awk's Another option might be to construct a regular expression that searches for all the words you're interested in, all at once. This has the benefit of using a single run of The result will contain all the interesting lines from Note that this is a fairly rudimentary search, without word boundaries, so if you search for "foo bar babar", you may get results you don't want. You can play with the regex yourself, though. :) Does that answer your question? 这篇关于使用awk匹配日志文件中的一列并打印整行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!-v
选项将每个单词放入脚本中,而不是在引用的脚本中扩展变量.您应该阅读 bash如何处理不同种类的报价. (有关该主题的一些Stackoverflow问题,请此处和$FILE
中所有有趣的行,并按它们出现在$FILE
中的顺序排列,而不是按您提供的单词进行排序.
awk ' $5=="acpid:" {print$0}' *filename*
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
'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" `
finish loopfor
loop for each word, then apply a different call to awk
, and show the results sequentially. For example, if you entered foo bar
into the $details
variable, you might get a list of foo
matches, followed by a list of bar
matches:read -a details
for i in "${details[@]}"; do
awk -v s="$i" '$5 == s' "$FILE"
done
-v
option to get each word into the script, rather than expanding the variable inside the quoted script. You should read about how bash deals with different kinds of quotes. (There are also a few Stackoverflow questions on the topic, here and here and elsewhere.)awk
to search through $FILE
:read -a details
re=""
for i in "${details[@]}"; do
re="$re${re:+|}$i"
done
awk -v re="$re" '$5 ~ re' "$FILE"
$FILE
in the order in which they appear in $FILE
, rather than ordered by the words you provided.