我正在尝试编写一个脚本来分析日志文件,我想让用户可以选择输入一个模式,然后在特定的列(第五列)中打印任何与该模式匹配的行终端的以下工作
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。:)
这能回答你的问题吗?