Linux中很多文本工具都使用到了正则表达式,正则表达式可以极大的简化linux系统管理工作,因为网上有很多正则相关的教程,所以这里不再讲述,我当时看的是菜鸟的正则表达式,看个一下午在实验几遍基本就会了,除了正向肯定预查,反向肯定预查这几个比较复杂一些,其他都是非常简单的,很多时候记不住也可以查询网上对着写,并不需要你实时记住。这里主要谈谈awk等用到正则表达式的文本处理工具。
awk的指令必须包含在单引号中。
awk -F'指定输入分隔符' 'BEGIN{做一些初始化工作} 一些过滤条件 {针对每行的工作}... END{最后收尾工作}'
中间的处理块可以有多个,通过过滤条件单每行都会走一遍过滤条件,其中BEGIN和END边只会执行一遍
awk -F: '{print $1,$3,$6}' /etc/passwd
等价于awk 'BEGIN{FS=":"} {print $1,$3,$6}' /etc/passwd
awk -F '[;:]'
指定多个分隔符awk -F: '{print $1,$3,$6}' OFS="\t" /etc/passwd
指定输出分隔符需要注意的是上面print $1,$3,$6
中的,
被替换成了分隔符,如果是print $1$3$6
则中间没有分隔符
awk'/hello/ {print}' test.sh
awk '!/hello/ {print}' test.sh
awk '/hello/ && /world/ {print}' test.sh
awk '/hello/ || /world/ {print}' test.sh
也可以写成awk '/hello|world/ {print}' test.sh
awk '$5 ~ /hello/ {print}' test.sh
awk '$5 !~ /hello/ {print}' test.sh
$ awk 'NR!=1{if($6 ~ /TIME|ESTABLISHED/) print > "1.txt"; else if($6 ~ /LISTEN/) print > "2.txt"; else print > "3.txt" }' netstat.txt
awk 'NR!=1{print > $6}' netstat.txt
其实使用了 >
重定向,上例子使用了if语句
awk 'NR!=1{a[$6]++;} END {for (i in a) print i ", " a[i];}' netstat.txt
$ x=5
$ y=10
$ export y
$ echo $x $y
5 10
$ awk -v val=$x '{print $1, $2, $3, $4+val, $5+ENVIRON["y"]}' OFS="\t" score.txt
Marry 2143 78 89 87
Jack 2321 66 83 55
Tom 2122 48 82 81
Mike 2537 87 102 105
Bob 2415 40 62 72
参数列表:
grep主要就是一个正则表达式的使用,其中需要注意正则有三种BREs、EREs和PREs。前两种不支持非贪婪匹配。grep默认是BREs,所以他?,+,|,{,},(,)
这种字符都需要用\
转义,另外他不支持\s,\S,\D,\d,\n
等字符。
sed命令在自动化脚本编写的过程还是经常用到的。
基本句式: sed -nfei [操作]
操作: n1,n2 动作
动作:
例子:
sed -e 's/hello/hi/g'
:替换文本,-e可以省略sed -e '1,2s/hello/hi/g' -e '3,4s/world/man/g
:等价于sed -e '1,2s/hello/hi/g;3,4s/world/man/g
sed s/hello \(world\)/\1 hi/g'
:群组匹配,可以使用\n选择前面的群组sort参数
sort test.txt >test.txt
不可用,因为> 是想清空文件,所以会导致文件在排序之前就清空了例子:
sort -t $'\t' -k 1 -u res.txt > res2.txt
以tab作为分隔符,按第一列排序并去重uniq参数
需要注意uniq需要文本是有序的,所以一般使用uniq的时候是用更早sort的管道后面
说说sort|uniq
和sort -u
,一直觉得很奇怪,两者有什么区别,功能是一样的。sort -u
是后面加入的,所以很多人还是使用了sort|uniq
, 目前推荐使用sort -u
,因为还少了进程间通讯。
http://www.baidu.com/index.html
http: / / www.baidu.com/1.html
http://post.baidu.com/index.html
http://mp3.baidu.com/index.html
http://www.baidu.com/3.html
http://post.baidu.com/2.html
得到如下结果:
3 www.baidu.com
2 post.baidu.com
1 mp3.baidu.com
解法1:grep -Po '(?<=//)(.*?)(?=/)' test.txt |sort |uniq -c|sort -nr
1.利用了Perl,他支持非贪婪,2.利用了正向和反向预查(正向预查是后面的(?=)) 3.利用了-o参数只输出匹配的内容
解法2:awk -F/ '{print $3}' test.txt |sort |uniq -c|sort -nr
指明了分割符号 直接取对应值
解法3:sed 's/http:\/\/\([^/]*\).*/\1/' test.txt|sort |uniq -c|sort -nr
基本的正则中小括号需要转义,如果采用-r参数即扩展的正则小括号不用转义
解法4: sed -e 's/http:\/\///' -e 's/\/.*//' | sort | uniq -c | sort -rn
采用了替换,先替换前面的,在替换后面的
需要注意awk不支持多维数组,采用了一种变通的方式,普通的使用没问题,但是如果需要存的值是一个map就不合适了,如下 文件 1-6列分别为deal od sum up lj day ,现在要计算sum up lj day 的累加和输出 输出也要是deal od sum up lj day也就是sum up lj day需要是一个map,不过awk做不到这点
{
updealids:{
od: {day,sum,up,lj}
}
}
awk 'BEGIN{OFS="\t"}{result[$1,$3,"sum"]+=$4;result[$1,$3,"up"]+=$5;result[$1,$3,"lj"]+=$6;result[$1,$3,"day"]=$2}\
END{for ( i in result) {split(i, a, SUBSEP); print result[i] ,a[1], a[2], a[3] }}' *
参考资料:
这篇文章就总结到这里,希望能够对你有所帮助!