2019-06-13-grep/sed/awk
Linux报“ ‘/usr/bin’ is not included in the PATH environment variable ”的解决方法: 1 2 利用/usr/bin vi 编辑之前改过环境变量: /usr/bin vi ~/.bashrc
find(文件目录的查找)
+n(n天以前), -n(n天以内)
选项
说明
-name
根据文件名匹配
-iname
忽略大小写
-regex pattern
基于正则进行文件名匹配
-user
根据属主匹配
-group
根据属组匹配
-uid
根据UID匹配
-gid
根据GID匹配
-nouser
匹配没有属主文件
-nogroup
匹配没有属组文件
-type f d c b l p s
匹配文件类型
-size k M G
根据文件大小
-atime -mtime -ctime
访问 修改 改变
-perm -mode /mode
根据权限匹配
-print -ls, ls -l
–
-exec/-ok command {} ;
–
-a -o -not
逻辑上的与 或 非
1 2 3 4 find /data/ -name "*.log" -type f -size +10k -exec cp {} /tmp \; find /data/ -iname "*.log" -type f -size +10k -m perm 644 -exec rm -rf {} \; find /data/ -name "*.log" -type f -mtime +30 -size +10M -exec mv {} /tmp/ \; find /data -not \( -user user1 -a -not -type d \)
grep(文本搜索工具,行)
grep [OPTION] PATTERN [FILE]
Search for PATTERN in each FILE.
Example: 1 grep -i 'hello world' menu.h main.c
选项
说明
--color=auto
对匹配到的文本着色显示
-v
反选
-i
忽略大小写
-n
显示行号
-c
统计匹配的行数
-f
根据模式文件处理
-E
使用ERE
-w
匹配整个单词
-e
实现多个选项
-o
仅显示匹配到的字符串
-A #
after, 后#行(tail -n)
-B #
before, 前#行(head -n)
-C #
前后各#行
示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 grep -f a.txt b.txt grep -v -f a.txt b.txt echo "a bc de" |xargs -n1 |grep -e 'a' -e 'bc' grep -E -v "^$|^#" /etc/httpd/conf/httpd.confecho "this is a test" |grep -o 'is' ifconfig eno16777736 |grep -o "\<\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\>" grep -Eo "(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])" seq 1 20 |grep -m 5 -E '[0-9]{2}' echo "a ab abc abcd abcde" |xargs -n1 |grep -E -w -o '[a-z]{2,3}' seq 1 20 |grep -c -E '[0-9]{2}' echo "a ab abc abcd abcde" |xargs -n1 |grep -n 'de$' seq 1 10 |grep 5 -B 3
sed(处理行,一次读取一行内容)
流编辑器, 过滤和替换文本.sed [选项] '模式1动作1; 模式2动作2; ...' 待处理File
工作原理: sed命令将当前处理的行存储在临时缓冲区–模式空间(临时缓冲区)进行处理, 处理完把结果输出, 并清空模式空间. 然后再将下一行读入模式空间进行处理输出, 以此类推, 直到最后一行; 还有一个空间叫 保持空间, 又称暂存空间 , 可以暂时存放一些处理的数据,但不能直接输出, 只能放到模式空间输出;这两个空间其实就是在内存中初始化的一个内存区域, 存放正在处理的数据和临时存放的数据; 默认工作模式输出模式空间内容
选项
说明
-n
只输出命令匹配的内容(不显示模式空间内容)
-r, –reg
开启支持扩展正则
-i
sed的修改结果直接应用于文件
-e
多个命令组合 或者用;分割
-f 脚本文件名
从sed脚本读入sed操作
动作(定位)
说明
x,y
x~y之间的行
x,+N
从x行开始向后的N的行
x,y!
查询不包括x和y行之间的行
$
最后一行
/pattern1/,/pattern2/
查询从匹配模式1~模式2之间的行
/pattern/pattern/
查询包含两个模式的行
x,/pattern/
从与x行~与pattern匹配行之间的行
动作(编辑命令)
说明
p
打印,输出指定行
d
删除指定行
a \string
在指定行后追加
i \string
在指定行前插入
c \string
行替换,用c后边的字符串替换原数据
r FILE
指定行后添加文件内容
w FILE
指定范围的内容另存至指定文件中
s/pattern/string/
查找并替换字串
n
读取下一个输入行, 用下一个命令处理新行
N
将当前读入行的下一行读取到当前的模式空间
g
将保持缓冲区的内容复制到模式缓冲区
G
将保持缓冲区的内容追加到模式缓冲区
示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 sed -n '/^blp5/p' /etc/services tail /etc/services |sed -n '1,3p' sed -n '1p;$p' test.txt` tail /etc/services |sed '/blp5/i \test' tail /etc/services |sed '/blp5/a \test' tail /etc/services |sed '/blp5/c \test' tail /etc/services |sed '2a \test' sed '1,2r /etc/issue' /etc/fstab sed '/oot/w /tmp/oot/txt' /etc/fstab tail /etc/services |sed '/blp5/,$d' sed '/^#/d;/^$/d' /etc/httpd/conf/httpd.conf sed '1,3d' test.txt tail /etc/services |sed 's/blp5/test/' tail /etc/services |sed '1,4s#blp5#test#' sed -i '/SELINUX/s/enforceing/disabled/g' /etc/selinux/config sed 's/l..e/&r/g' sed 's#\(l..e\)#\1r#g' sed 's#l\(..e\)#L\1#g' seq 6 |sed '/^$/d; 1,3G' seq 6 |sed 'n; d' seq 6 |sed '/5/{x; p; x}' seq 6 |sed 'N; s/\n/ /' sed 'N;s#\n#=#g' seq 6 |sed '$!N; $!D' seq 6 |sed -n '/3/,/6/' p
awk (先读取行, 再提取列)
awk是一个处理文本的编程语言工具, 能用简短的程序处理标准输入或文件、数据排序、计算以及生成报表等等
awk 引用shell变量使用 -v 或者 双引号+单引号即可
1 2 awk -v STR=hello '{print STR, $NF}' test.txt` STR='Hello' ; echo |awk '{print "' ${STR} '"}' `
Usage:
awk 选项 '条件1{动作1} 条件2{动作2} ...' file
awk -F: '{print $1 >>"/tmp/awk.log"}' test.txt # -F ‘[ :\t;]’
条件/模式: 条件也即模式: BEGIN, 空模式, END模式
动作:
{ print 动作1,动作2, … } # 打印后则默认空格隔开; 若没有逗号隔开, 则会连在一起
{ print 动作1; print 动作2 } # 多个动作用分号隔开1 awk -F ":" '{ if($3<500) { print $1,"系统用户" } else{ print $1,"普通用户" }}' /etc/passwd
变量名
描述
FS, Field Separator
输入字段(列)分隔符,默认是空格或制表符 BEGIN{FS=”:”}
OFS
输出字段(列)分隔符,默认是空格
RS, Record Separator
输入记录(行)分隔符,默认是换行符\n
ORS
输出记录(行分隔符,默认是换行符\n
–
–
NF, Number Field
统计当前记录中字段(列)个数,列号
NR, Number Record
行号,当前处理的文本行的行号
FNR
同NR,各文件分别计数的行号
$0
当前读入整行数据
$n
当前读入行的第n个字段,第n列
FILENAME
显示文件名
示例:
FS OFS(输入输出字段分割符)1 2 3 awk 'BEGIN{FS=":"}{print $1,$2}' /etc/passwd |head -n5 awk 'BEGIN{FS=":";OFS=":"}{print $1,$2}' /etc/passwd |head -n5 awk 'BEGIN{FS=":"}{print $1"#"$2}' /etc/passwd |head -n5
RS ORS(输入输出记录分隔符)1 echo "www.baidu.com/user/test.html" |awk 'BEGIN{RS="/"}{print $0}'
NF(列号,统计当前字段个数) 1 2 echo "a b c d e f" |awk '{print NF}' echo "a b c d e f" |awk '{print $NF}'
NR FNR(行号,统计记录编号)1 2 3 tail -n5 /etc/services |awk '{print NR,$0}' tail -n5 /etc/services |awk 'END{print NR}' cat /etc/passwd |grep "/bin/bash" |awk 'BEGIN{FS=":"} {printf $1 "\t" $3 "\t 行号:"NR "\t 字段数:"NF "\n"}'
格式化输出1 2 awk -F: '{print "%-12s %-6s %-8s\n", $1, $2, $NF}' /etc/passwd netstat -an |awk '$6 ~ /LISTEN/&&NR>=1&&NR<=10 {print NR, $4, $5,$6}' OFS="\t"
须知: 在awk中, 有3种情况表达式为假: 数字是0, 空字符串和未定义的值. 数值运算, 未定义变量初始值为0; 字符运算; 未定义变量初始值为空.
Nginx 日志分析:
114.242.26.65 - - [22/Mar/2017:08:41:08 +0800] “GET /css/20151103Style.css HTTP/1.1” 200 9041 “http://sz.cdn-my.mobiletrain.org/ “ “Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) ApplwWebKit/537.36 (HTML, like Gecko) Chrome/50.02661.102 Safari/537.36”
1 2 grep '05/Sep/2017' cd.mobiletrain.org.log |wc -l awk '$4>="[05/sep/2017:08:00:00" && "[05/sep/2017:09:00:00" {print $0}' sz.mobiletrain.log |wc -l
2.统计2017年9月5日 一天访问最多的10个IP(top 10)
1 2 grep '05/Sep/2017' sz.mobiletrain.org.log |awk '{ips[$1]++} END{for(i in ips){print i,ips[i]}}' |sort -k2 -nr |head -n10 awk '05\/Sep\/2017' sz.mobiletrain.org.log |awk '{ips[$1]++} END{for(i in ips){print i,ips[i]}}' |sort -k2 -nr |head -n10
1 grep '05/Sep/2017' sz.mobiletrain.org.log |awk '{ips[$1]++} END{for(i in ips){if(ips[i]>100){print i,ips[i]}}}'
4.统计2017年9月5日 访问最多的10个页面($request top 10)
1 awk '/05\/Sep\/2017/ {urls[$7]++} END{for(i in urls){print i,urls[i]}}' sz.mobiletrain.org.log |sort -k1 -rn |head -n10
5.统计2017年9月5日 每个url访问内容总大小($body_bytes_sent)
1 awk '/05\/Sep\/2017/ {urls[$7]++; size[$7]+=$10} END{for(i in urls){print urls[i],size[i],i}}' sz.mobiletrain.org.log |sort -k1 -rn |head -n10
6.统计2017年9月5日 每个IP访问状态码数量($status)
1 awk '/05\/Sep/\2017/ {ip_code[$1" "$9]++} END{for(i in ip_code){print i,ip_code[i]}}' sz.mobiletrain.org |sort -k1 -rn |head -n10
7.统计2017年9月5日 访问状态码为404及出现次数($status)
1 awk '/05\/Sep\/2017/ {if($9=="404"){ip_code[$1" "$9]++} END{for(i in ip_code){print i,ip_code[i]}}}' sz.mobiletrain.org.log
1 date =$(date -d '-1 minute' +%d/%b/%Y:%H:%M); awk -v date =$date '$0 ~ date {i++} END{print i}' sz.mobiletrain.org.log
9.统计2017年9月5日 8:30-9:00, 访问状态码是404
1 awk '$4>="[05/Sep/2017:08:30:00 && [05/Sep/2017:09:00:00" {if($9=="404"){ip_code[$1" "$9]++} for(i in ip_code){print i,ip_code[i]}}' sz.mobiletrain.org.log
1 awk '/05\/09\/2017/ {code[$9]++;total++} END{for(i in code){printf i"\t"; printf code[i]"\t"; printf "%.2f",code[i]/total*100; print "%"}}' sz.mobiletrain.org.log
1 awk '{print $1}' access.log |sort -r |uniq -c |wc -l
1 awk '{print $7}' access.log |wc -l
1 awk '{print $11}' access.log |sort -r |uniq -c |wc -l
1 awk '{print $1}' access.log |sort |uniq -c |sort -nr |head -n20
1 2 sed -n "/2019:09:00" /,/2019:12:00/"p access.log `awk '/2019:09:00/,/2019:12:00' access.log |wc -l
16.状态码404、502、503、500、499等错误信息页面,打错误出现次数大于20的IP地址
1 awk '{if($9~/502|499|500|503|404/) print $1, $9}' access.log |sort |uniq -c |sort -nr |awk '{if($1>20) print $2}'
1 awk '{print $7}' access.log |sort |uniq -c |sort -nr |head -n20
18.请求处理时间大于5s的URL,打印出时间、URL、访客、IP
1 awk '{if($NF>5) print $NF, $7, $1}' access.log |sort -nr |more
continue: 在循环中不执行continue下面的代码,转而进入下一轮循环
break: 结束并退出整个循环
exit: 退出脚本,常带一个整数给系统,如 exit 0
return: 在函数中将数据返回或返回一个结果给调用函数的脚本
break: 是立马跳出循环, continue: 是跳出当前条件循环, 继续下一轮条件循环, exit: 是直接退出整个脚本
琐碎知识点:
项目
说明
$0
脚本自身名字
$?
返回上条命令是否执行成功, 0执行成功, 非零失败
S#
参数总数
$*
参数都被看作一个字符串
$@
每个参数被看作独立字符串
$$
当前进程PID
$!
上一条运行后台进程PID