我需要解析apache-access日志文件,它有16个以空格分隔的列,即
xyz abc ... ... home?querystring
我需要计算该文件中每个页面的总点击次数,即忽略查询字符串的主页点击总数
对于少数行,url是第16列,而其他行是14或15.因此我需要以相反的顺序解析每一行(获取最后一列,忽略最后一列的查询字符串,聚合页面命中)
我是linux,shell脚本的新手。我如何处理此问题,是否必须查看awk或shell脚本。你能给出一个可以执行这种任务的小样本代码。
答案:perl one liner解决了这个问题
perl -lane |标量数组
答案 0 :(得分:0)
对初学者来说,如果你只对第14-16栏的工作感兴趣,我会先运行
cut -d\ -f14-16 <input_file.log> | awk '{ one = match($1,/www/)
two = match($2,/www/)
three = match($3,/www/)
if (one)
print $1
else if(two)
print $2
else if(three)
注意:d \
后面有两个空格然后,您可以非常轻松地计算您看到的网址。我也认为使用几行python或perl可以更轻松地解决这个问题。
答案 1 :(得分:0)
您可以使用read
bash命令逐行读取:
while read my_variable; do
echo "The text is: $my_variable"
done
要从特定文件获取输入,请使用输入重定向<
:
while read my_variable; do
echo "The text is: $my_variable"
done < my_logfile
现在,要获取最后一列,您可以使用${var##* }
构造。例如,如果变量my_var
是字符串some_file_name
,那么${my_var##*_}
是相同的字符串,但在删除最后_
之前的所有内容(包括)。
我们提出:
while read line; do
echo "The last column is: ${line##* }"
done < my_logfile
如果您想将其回显到另一个文件,请使用>>
重定向:
while read line; do
echo "The last column is: ${line##* }" >> another_file
done < my_logfile
现在,要取消查询字符串,您可以使用相同的技术:
while read line; do
last_column="${line##* }"
url="${last_column%%\?*}"
echo "The last column without querystring is: $url" >> another_file
done < my_logfile
这一次,我们有%%?*
而不是##*?
,因为我们希望在 {/ em> ?
之后删除之后的内容在最后一个之前。 (请注意,我已经转义了字符?
,这对于bash来说是特殊的。)您可以阅读所有相关信息here。
我不明白从哪里获得页面点击,但我认为主要的想法就在那里。
编辑:现在代码可以运行了。我忘记了do
重击键。此外,我们需要使用>>
而不是>
,以便在每次another_file
时都不会覆盖echo "..." > another_file
。通过使用>>
,我们将附加到文件中。我还更正了%%
而不是##
。
答案 2 :(得分:0)
如果没有几行具体的样本输入和预期的输出,很难说,但听起来你只需要:
awk -F'[ ?]' '{sum[$(NF-1)]++} END{for (url in sum) print url, sum[url]}' file
例如:
$ cat file
xyz abc ... ... http://www.google.com?querystring
xyz abc ... ... some other http://www.google.com?querystring1
xyz abc ... some stuff we ignore http://yahoo.com?querystring1
$
$ awk -F'[ ?]' '{sum[$(NF-1)]++} END{for (url in sum) print url, sum[url]}' file
http://www.google.com 2
http://yahoo.com 1