参考:李中国老师的课件
目录
可编程过滤器awk
历史
略
awk: 为什么叫做可编程过滤器 ?
- awk 可以读标准输入并写标准输出 , 因此符合经典过滤
器模式的程序定义 - 但是 awk 与 grep,tr,wc,sort,uniq 等功能单一的过滤器程序的最大不同之处 , 是它的文本过滤功能需要通过用户自己编程去实现 , 因此更加强大、丰富、灵活
准备数据:emp.data,分隔符为空格
Beth 4.00 0
Dan 3.75 0
Kathy 4.00 10
Mark 5.00 20
Mary 5.50 22
Susie 4.25 18
awk 可编程过滤器的五种使用方式
方式一
cat emp.data | awk '$3 > 0 { print $1, $2 * $3 } '
方式二
awk '$3 > 0 { print $1, $2 * $3 } '
emp.data
方式三
awk -f programfile
emp.data
方式四
cat emp.data | awk -f programfile
方式五
chmod +x programfile
cat emp.data | ./programfile
或
./programfile emp.data
awk源文件programfile: 注意第一行#! /usr/bin/awk -f
#! /usr/bin/awk -f
$3 > 0 { print $1, $2 * $3 }
#$3 > 0 {print $1,$2*$3}
#$3 > 0 {print $1, $2*$3}
#$3 > 0 {print $1, $2* $3 }
#$3 > 0 {print $1"\t"$2*$3}
awk 程序的基本结构
awk '模式 + { 动作 }'
只有动作:默认模式为匹配所有行
awk ’ { print $1 } ’ emp.data
只有模式:默认动作为打印匹配的行
awk ’ $3 == 0 ’ emp.data
awk 程序的特殊模式:
BEGIN
在读入文件之前执行。
命令行
[sy@sy-pc script]$ awk 'BEGIN {print "Name Rate Hours";print "" }{ print }' emp.data
Name Rate Hours
Beth 4.00 0
Dan 3.75 0
Kathy 4.00 10
Mark 5.00 20
Mary 5.50 22
Susie 4.25 18
程序文件
#注意:BEGIN 与 { 必须在同一行
[sy@sy-pc script]$ cat programfile.sh
#! /usr/bin/awk -f
BEGIN { #注意:这里的BEGIN 与 { 必须在同一行
print "Name Rate Hours"
print ""
}
{
print
}
[sy@sy-pc script]$ ./programfile.sh emp.data
Name Rate Hours
Beth 4.00 0
Dan 3.75 0
Kathy 4.00 10
Mark 5.00 20
Mary 5.50 22
Susie 4.25 18
END
在读完文件之后执行。
#注意:END与 { 必须在同一行
[sy@sy-pc script]$ cat programfile.sh
#! /usr/bin/awk -f
$3>15{emp=emp+1} #每个符号之间可以有空格 $3 > 15 { emp = emp + 1 }
END { #注意:END与 { 必须在同一行
print emp, "employess worked more than 15 hours"
}
[sy@sy-pc script]$ ./programfile.sh emp.data
3 employess worked more than 15 hours
awk 程序的特殊变量: NR 与 NF
- NR: 记录当前行号
- NF: 当前行内字段数
- $0: 当前整行的内容
- F: 指定分隔符
[sy@sy-pc script]$ awk '{print NR, $0}' emp.data
1 Beth 4.00 0
2 Dan 3.75 0
3 Kathy 4.00 10
4 Mark 5.00 20
5 Mary 5.50 22
6 Susie 4.25 18
[sy@sy-pc script]$ cat programfile.sh
#! /usr/bin/awk -f
{print NR, $0}
$ ./programfile.sh emp.data
计算某文件有多少个字符:
思考:程序中为什么要+1?
[sy@sy-pc script]$ cat programfile.sh
#! /usr/bin/awk -f
{ nc=nc+=length($0) + 1
nw=nw+NF
}
END {
print NR, "lines,", nw, "words,", nc, "characters"
}
[sy@sy-pc script]$ ./programfile.sh emp.data
6 lines, 18 words, 77 characters
-F 指定分隔符的使用方式
[root@sy-pc ~]$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@sy-pc ~]$ cat /etc/passwd | awk -F : 'BEGIN {print "name\tshell"} {print $1","$7} END {print "blue,/bin/nosh"}'
name shell
root,/bin/bash
bin,/sbin/nologin
daemon,/sbin/nologin
adm,/sbin/nologin
......
blue,/bin/nosh
awk 控制结构
与 C 语言一样 ,awk 支持 if 语句、 for 循环、 while 循环等控制语句 ( 具有相同的语法 ):
将负数转成正数显示:
[sy@sy-pc script]$ cat programfile.sh
#! /usr/bin/awk -f
{
for (i = 1; i <= NF; i = i + 1){
if ($i < 0)
$i = -$i
}
print
}
或者
[sy@sy-pc script]$ cat programfile.sh
#! /usr/bin/awk -f
{ for (i = 1; i <= NF; i = i + 1) if ($i < 0) $i = -$i
print
}
awk 数组
将文件内容,按每一行倒叙显示:
[sy@sy-pc script]$ cat programfile.sh
#! /usr/bin/awk -f
{ line[NR]=$0}
END { for (i=NR; i>0; i=i-1)
print line[i]
}
[sy@sy-pc script]$ ./programfile.sh emp.data
Susie 4.25 18
Mary 5.50 22
Mark 5.00 20
Kathy 4.00 10
Dan 3.75 0
Beth 4.00 0
流编辑器sed
简介
- sed = stream editor
- 流编辑器 sed
- 它编辑的对象通常是 Unix 管道中的文本流 , 故名
- 诞生于 1973 – 1974 年 , 发明人是贝尔实验室的 LeeE. McMahon ( 毕业于哈佛大学 )
- 常常作为过滤器应用于管道之中 , 实现对文本的自动编辑处理 ; 与 awk 类似 , 其编辑功能同样是可编程的(programmable)
- sed 是标准的过滤器模式的程序
- … | sed ‘s/xxx/yyy/g’ | …
替换命令 s
sed 最基本、最重要的命令 s :文本替换
注意:
- 变更对象限制在特定的行,例如只想替换第2行内容,只需写为"2s"
- 无g 匹配到一块后,停止这一行后面字符串的匹配;
- 有g 匹配所有的字符串,即贪婪匹配;
- 正则表达式及替换文本的分割符 / 可以换成其它符号;
- 在被替换字符串中 , 可以用符号 & 表示前面正则表达式匹配的内容;这一特性在进行文本替换时非常有用;
- 在正则表达式及被替换字符换中,可用 \number 表示第几个匹配的字符串;匹配字符串如需参加编号 , 则用 \( 和 \) 标志:
- 无-r参数,大括号、小括号 需要加转义字符
- 有-r 参数,可以省略 正则表达式中的转义字符;
例1:
[sy@sy-pc script]$ echo "123abc" | sed 's/[0-9][0-9]*/& &/'
123 123abc
例2:
[sy@sy-pc script]$ cat input.txt
2014-03-03,37.92,38.13,37.49,37.78,29717500,37.78
2014-03-04,37.93,38.14,37.50,37.77,29717500,37.78
2014-04-05,37.94,38.15,37.51,37.77,29717511,37.79
2014-04-06,37.95,38.16,37.52,37.76,29717511,37.79
[sy@sy-pc script]$ cat input.txt | sed 's/,/\t/g' > output.txt
[sy@sy-pc script]$ cat output.txt
2014-03-03 37.92 38.13 37.49 37.78 29717500 37.78
2014-03-04 37.93 38.14 37.50 37.77 29717500 37.78
2014-04-05 37.94 38.15 37.51 37.77 29717511 37.79
2014-04-06 37.95 38.16 37.52 37.76 29717511 37.79
只处理第2行 2s
[sy@sy-pc script]$ cat input.txt | sed '2s/,/\t/g' > output.txt
[sy@sy-pc script]$ cat output.txt
2014-03-03,37.92,38.13,37.49,37.78,29717500,37.78
2014-03-04 37.93 38.14 37.50 37.77 29717500 37.78
2014-04-05,37.94,38.15,37.51,37.77,29717511,37.79
2014-04-06,37.95,38.16,37.52,37.76,29717511,37.79
例3:
[sy@sy-pc script]$ cat telephone.txt
4000001476
4000000049
4000000041
4000002754
[sy@sy-pc script]$ cat telephone.txt | sed 's/[0-9]\{3\}/(&)/'
[sy@sy-pc script]$ cat telephone.txt | sed -r 's/[0-9]{3}/(&)/'
(400)0001476
(400)0000049
(400)0000041
(400)0002754
例4:
[sy@sy-pc script]$ cat telephone.txt | sed 's/\([0-9]\{3\}\)\([0-9]\{3\}\)/\1-\2-/'
[sy@sy-pc script]$ cat telephone.txt | sed -r 's/([0-9]{3})([0-9]{3})/\1-\2-/'
400-000-1476
400-000-0049
400-000-0041
400-000-2754
参数 -i
永久关闭CentOS 7的SELInux
sed -i "s#SELINUX=enforcing#SELINUX=disabled#g" /etc/selinux/config