Linux Shell 脚本:如何将文本文档中的特定字段与 if 语句中的特定文本进行比较
Linux Shell Script: How to compare a specific field in a text document with specific text in an if statement
我有一个名为 transfer.log 的文件,其中包含一些 Apache 日志。我需要计算每个 IP 地址记录了多少 GET 请求。我知道如何访问文件并循环遍历文件中的行,但我无法将每行中的第 6 个字段与 "GET".
进行比较
#!/bin/bash
while read p;
do
name=( $(awk '{print }' p))
echo $name
if [ "$name" == "GET" ]
then
echo "yes"
else
echo "no"
fi
done < transfer.log
目前,当我 运行 脚本 "no" 被打印 5 次时,我收到一条错误消息,提示 awk 无法打开文件 "p"。当我在变量声明中将 p 更改为 transfer.log 时,我可以获得 echo $name 输出“GET(带引号),但它显然永远不会改变,因为它正在访问整个文件而不是新行p.
我需要知道每次执行 while 循环时如何将 p 的第 6 列分配给我的变量名。另外,我很困惑为什么我的循环只迭代 5 次而不是 6 次。
我的 transfer.log 看起来像这样:
140.211.167.27 - - [15/Oct/2012:23:11:38 +0000] "GET / HTTP/1.1" 200 2963 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4"
140.211.167.27 - - [15/Oct/2012:23:11:46 +0000] "GET /systems/ganeti/index HTTP/1.1" 200 5918 "https://wiki.osuosl.org/systems/index" "Mozilla/5.0(X11; Linux x86_64) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4"
140.211.167.9 - - [15/Oct/2012:23:17:33 +0000] "GET /resources/index HTTP/1.1" 200 3411 "https://wiki.osuosl.org/index" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0.1"
140.211.167.25 - - [15/Oct/2012:16:02:07 +0000] "GET /index HTTP/1.1" 200 2673 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0.1"
66.249.74.101 - - [15/Oct/2012:02:20:14 +0000] "GET /robots.txt HTTP/1.1" 404 2458 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
128.193.164.34 - - [15/Oct/2012:12:41:18 +0000] "POST /rpc/xmlrpc HTTP/1.0" 200 8328 "-" "PHP XMLRPC 1.0"
最后,我需要计算每个特定 IP 地址记录了多少 GET 请求,并按照从最少到最多的 GET 请求对地址进行排序。
下面一行是错误的:
name=( $(awk '{print }' p))
您应该将其替换为:
name=$(echo "$p" | awk '{print }')
您将变量名 p
传递给了需要文件名的 awk
。此外,外括号是多余的。
我尝试解析日志文件,供大家参考:
#!/bin/bash
howmanyGET=0
loopcounter=0
while read line;do
#echo "Line # $loopcounter: $line"
((loopcounter++))
name=`echo $line | awk '{print }'`
#name=( $(awk '{print }' p))
#echo $name
name=${name:1:3}
echo $name
if [ "$name" == "GET" ]
then
echo "yes"
((howmanyGET++))
else
echo "no"
fi
done < transfer.log
echo "GET: $howmanyGET"
echo "loop: $loopcounter"
此处输出:
$ bash counter.sh
GET
yes
GET
yes
GET
yes
GET
yes
GET
yes
POS
no
GET: 5
loop: 6
希望对您有所帮助。
您可以使用以下 awk
命令来完成此操作:
$ awk '{if(=="\"GET")ip[]++; else ip[]+=0}END{for(elem in ip){print elem, ip[elem]}}' input.log | sort -k2nr
140.211.167.27 2
140.211.167.25 1
140.211.167.9 1
66.249.74.101 1
128.193.164.34 0
说明:
{if(=="\"GET")ip[]++; else ip[]+=0}
在文件的每一行上,它将检查第 6 个字段,如果它等于 "GET
,它将递增一个索引为 ip 的数组;如果第 6 个字段不等于 "GET
,它会将 0 添加到数组中,以便考虑到已经完成某些操作的 ip POST
如果您不识别它,则可以删除此逻辑。
- 然后在文件末尾它会打印每个
ip
加上 GET
- 所有内容都通过管道传输到
sort
命令,该命令将使用第二个字段对输出进行排序,并按相反的数字顺序排列
我有一个名为 transfer.log 的文件,其中包含一些 Apache 日志。我需要计算每个 IP 地址记录了多少 GET 请求。我知道如何访问文件并循环遍历文件中的行,但我无法将每行中的第 6 个字段与 "GET".
进行比较#!/bin/bash
while read p;
do
name=( $(awk '{print }' p))
echo $name
if [ "$name" == "GET" ]
then
echo "yes"
else
echo "no"
fi
done < transfer.log
目前,当我 运行 脚本 "no" 被打印 5 次时,我收到一条错误消息,提示 awk 无法打开文件 "p"。当我在变量声明中将 p 更改为 transfer.log 时,我可以获得 echo $name 输出“GET(带引号),但它显然永远不会改变,因为它正在访问整个文件而不是新行p.
我需要知道每次执行 while 循环时如何将 p 的第 6 列分配给我的变量名。另外,我很困惑为什么我的循环只迭代 5 次而不是 6 次。
我的 transfer.log 看起来像这样:
140.211.167.27 - - [15/Oct/2012:23:11:38 +0000] "GET / HTTP/1.1" 200 2963 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4"
140.211.167.27 - - [15/Oct/2012:23:11:46 +0000] "GET /systems/ganeti/index HTTP/1.1" 200 5918 "https://wiki.osuosl.org/systems/index" "Mozilla/5.0(X11; Linux x86_64) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4"
140.211.167.9 - - [15/Oct/2012:23:17:33 +0000] "GET /resources/index HTTP/1.1" 200 3411 "https://wiki.osuosl.org/index" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0.1"
140.211.167.25 - - [15/Oct/2012:16:02:07 +0000] "GET /index HTTP/1.1" 200 2673 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0.1"
66.249.74.101 - - [15/Oct/2012:02:20:14 +0000] "GET /robots.txt HTTP/1.1" 404 2458 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
128.193.164.34 - - [15/Oct/2012:12:41:18 +0000] "POST /rpc/xmlrpc HTTP/1.0" 200 8328 "-" "PHP XMLRPC 1.0"
最后,我需要计算每个特定 IP 地址记录了多少 GET 请求,并按照从最少到最多的 GET 请求对地址进行排序。
下面一行是错误的:
name=( $(awk '{print }' p))
您应该将其替换为:
name=$(echo "$p" | awk '{print }')
您将变量名 p
传递给了需要文件名的 awk
。此外,外括号是多余的。
我尝试解析日志文件,供大家参考:
#!/bin/bash
howmanyGET=0
loopcounter=0
while read line;do
#echo "Line # $loopcounter: $line"
((loopcounter++))
name=`echo $line | awk '{print }'`
#name=( $(awk '{print }' p))
#echo $name
name=${name:1:3}
echo $name
if [ "$name" == "GET" ]
then
echo "yes"
((howmanyGET++))
else
echo "no"
fi
done < transfer.log
echo "GET: $howmanyGET"
echo "loop: $loopcounter"
此处输出:
$ bash counter.sh
GET
yes
GET
yes
GET
yes
GET
yes
GET
yes
POS
no
GET: 5
loop: 6
希望对您有所帮助。
您可以使用以下 awk
命令来完成此操作:
$ awk '{if(=="\"GET")ip[]++; else ip[]+=0}END{for(elem in ip){print elem, ip[elem]}}' input.log | sort -k2nr
140.211.167.27 2
140.211.167.25 1
140.211.167.9 1
66.249.74.101 1
128.193.164.34 0
说明:
{if(=="\"GET")ip[]++; else ip[]+=0}
在文件的每一行上,它将检查第 6 个字段,如果它等于"GET
,它将递增一个索引为 ip 的数组;如果第 6 个字段不等于"GET
,它会将 0 添加到数组中,以便考虑到已经完成某些操作的 ipPOST
如果您不识别它,则可以删除此逻辑。- 然后在文件末尾它会打印每个
ip
加上GET
- 所有内容都通过管道传输到
sort
命令,该命令将使用第二个字段对输出进行排序,并按相反的数字顺序排列