grep
- 作用:过滤文本内容 | 选项 | 描述 | | —- | —- | | -E:—extendedd—regexp | 扩展正则表达式ERE | | -i:—ignore—case | 忽略大小写 | | -n:—line—number | 打印行号 | | -o:—only—matching | 只打印匹配的内容 | | -c:—count | 只打印每个文件匹配的行数 | | -B:—before—context=NUM | 打印匹配的前几行 | | -A:—after-context=NUM | 打印匹配的后几行 | | -C:—context=NUM | 打印匹配的前后几行 | | —color[=WHEN] | 匹配的字体颜色,别名已经定义了 | | -v:—invert—match | 打印不匹配的行 | | -e | 多点操作eg:grep -e “^s” -e “s$” |
实例
- 样本文件内容 ```bash [root@server1 ~]# cat test1 asdkahsduoa aslkdsl oiofr sdjo A F aSDD CASDC
asdo ca
<a name="Xzem7"></a>### 实例1: -i选项打印出所有的a无论大小写```bash[root@server1 ~]# grep -i 'a' test1asdkahsduoaaslkdslAaSDDCASDCasdoca
实例2: -n选项
打印出所有的a无论大小写,并且显示该字符串所在的行
[root@server1 ~]# grep -in 'a' test11:asdkahsduoa2:aslkdsl5:A7:aSDD8:CASDC10:asdo11:ca
实例3:-o选项
仅仅打印出所有匹配的字符串
[root@server1 ~]# grep -io 'a' test1aaaaAaAaa
实例4:-c选项
打印出匹配的字符串有多少行
[root@server1 ~]# grep -ic 'a' test17
实例5:-B
打印出字符S前面两行
[root@server1 ~]# grep -B 2 'S' test1AFaSDDCASDC
实例6:-A
打印出字符S后面两行
[root@server1 ~]# grep -A 2 'S' test1aSDDCASDCasdo
实例7:-C
打印出字符S前后两行
[root@server1 ~]# grep -C 2 'S' test1AFaSDDCASDCasdo
实例8:取反 -v
打印出不包含大小写s的所有行
[root@server1 ~]# grep -iv 'S' test1oiofrAFca
用法
grep可以直接从文件当中搜索某个关键词,也可以从标准输入里面搜索
[root@server1 ~]# grep root /etc/passwdroot:x:0:0:root:/root:/bin/bashoperator:x:11:0:operator:/root:/sbin/nologin[root@server1 ~]# cat /etc/passwd | grep 'root'root:x:0:0:root:/root:/bin/bashoperator:x:11:0:operator:/root:/sbin/nologin
正则表达式(基于grep)
正则表达式是为了处理大量文本或者字符串而定义的一套规则,通过定义特殊的符号辅助,系统管理员可以快速过滤、输出或替换需要的字符串。
Linux正则表达式一般以行为单位。
基础正则表达式
| 符号 | 描述 |
|---|---|
| . | 可以匹配任意单个字符(必须存在) |
| ^ | 匹配以某个字符开头的行 |
| $ | 匹配以某个字符结尾的行 |
| * | 匹配前面一个字符出现0次或多次;a*b |
| .* | 表示任意长度的任意字符 |
| [] | 表示匹配括号内的一个字符 |
| [^] | 匹配[^字符]之外的任意一个字符 |
| < | 锚定单词首部;<root |
| > | 锚定单词尾部 |
| {m,n} | 表示前面的字符至少出现m次,至多出现n次 |
| () | 表示对某个单词进行分组,\1表示第一个分组进行调用 |
扩展正则
- egrep …
- grep -E …
- 扩展正则支持所有基础正则
- 扩展正则中{}和[]不用转义符号可以直接使用 | 符号 | 描述 | | —- | —- | | + | 表示前面的字符至少出现一次的情况 | | | | 表示或 | | ? | 表示前面的字符至多出现一次的情况 |
常用情景
查看配置文件时去除所有注释和空行
[root@server1 ~]# grep -Ev '^#|^$' /etc/ssh/sshd_config
sed
sed命令是利用script来处理文本文件,sed可依照script的指令,来处理、编辑文本文件。
sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等等。
语法
sed [-hnV][-e<script>][-f<script文件>][文本文件]
参数说明
-e<script>或--expression=<script>,以选项中指定的script来处理输入的文本文件,这里的script是直接写在命令行里的。-f<script文件名>或--filename=<script文件名>,以选项中指定的script文件来处理输入的文本文件。
-h或—help显示帮助-n或--quiet或--silent,仅显示script处理后的结果。-v或--version,显示版本信息。
动作说明
a :新增, a 的后面可以接字符串,而这些字符串会在新的一行出现(目前的下一行)~
c :取代, c 的后面可以接字符串,这些字符串可以取代 n1,n2 之间的行(用于整行替换)!
d :删除,因为是删除,所以 d 后面通常不接任何字符串;
i :插入, i 的后面可以接字符串,而这些字符串会在新的一行出现(目前的上一行);
p :打印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行
s :取代,可以直接进行取代的工作!通常这个 s 的动作可以搭配正规表示法!例如 1,20s/old/new/g (用于行内替换)
实例
- 准备测试文件
在test文件第四行后添加一行,并将结果输出到标准输出[root@server1 ~]# cat testline oneline twoline threeline fourline five
[root@server1 ~]# sed -e 4a\newline testline oneline twoline threeline fournewlineline five
以行为单位的新增/删除
将 /etc/passwd 的内容列出并且列印行号,同时,请将第 2~5 行删除
[root@localhost ~]# nl /etc/passwd | sed '2,5d'1 root:x:0:0:root:/root:/bin/bash6 sync:x:5:0:sync:/sbin:/bin/sync7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown8 halt:x:7:0:halt:/sbin:/sbin/halt9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin10 operator:x:11:0:operator:/root:/sbin/nologin
sed 的动作为 ‘2,5d’ ,那个 d 就是删除!因为 2-5 行给他删除了,所以显示的数据就没有 2-5 行。 另外,注意一下,原本应该是要下达 sed -e 才对,没有 -e 也行!同时也要注意的是, 如果 sed 后面直接接的动作,请务必以 ‘’ 两个单引号括住!
只要删除第2行
root@localhost ~]# nl /etc/passwd | sed '2d'1 root:x:0:0:root:/root:/bin/bash3 daemon:x:2:2:daemon:/sbin:/sbin/nologin4 adm:x:3:4:adm:/var/adm:/sbin/nologin5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin6 sync:x:5:0:sync:/sbin:/bin/sync7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown8 halt:x:7:0:halt:/sbin:/sbin/halt9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin10 operator:x:11:0:operator:/root:/sbin/nologin
删除第3到最后一行
[root@localhost ~]# nl /etc/passwd | sed '3,$d'1 root:x:0:0:root:/root:/bin/bash2 bin:x:1:1:bin:/bin:/sbin/nologin
在第二行后(即第三行)加入一行“hello world”
[root@localhost ~]# nl /etc/passwd | sed '2a hello world'1 root:x:0:0:root:/root:/bin/bash2 bin:x:1:1:bin:/bin:/sbin/nologinhello world3 daemon:x:2:2:daemon:/sbin:/sbin/nologin4 adm:x:3:4:adm:/var/adm:/sbin/nologin
加在第二行前面
[root@localhost ~]# nl /etc/passwd | sed '2i hello world'1 root:x:0:0:root:/root:/bin/bashhello world2 bin:x:1:1:bin:/bin:/sbin/nologin3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
增加多行文字
[root@localhost ~]# nl /etc/passwd | sed '2a hello world\> nihao'1 root:x:0:0:root:/root:/bin/bash2 bin:x:1:1:bin:/bin:/sbin/nologinhello worldnihao3 daemon:x:2:2:daemon:/sbin:/sbin/nologin4 adm:x:3:4:adm:/var/adm:/sbin/nologin
以行为单位替换/显示
将第2-5行的内容取代成为『No 2-5 number』
[root@localhost ~]# nl /etc/passwd | sed '2,5c No 2-5 number'1 root:x:0:0:root:/root:/bin/bashNo 2-5 number6 sync:x:5:0:sync:/sbin:/bin/sync7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
仅列出 /etc/passwd 文件内的第 5-7 行
[root@localhost ~]# nl /etc/passwd | sed -n '5,7p'5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin6 sync:x:5:0:sync:/sbin:/bin/sync7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
数据的搜寻与显示
搜索 /etc/passwd有root关键字的行
[root@localhost ~]# nl /etc/passwd | sed -n '/root/p'1 root:x:0:0:root:/root:/bin/bash10 operator:x:11:0:operator:/root:/sbin/nologin
数据的搜寻与删除
删除/etc/passwd所有包含root的行,其他行输出
[root@localhost ~]# nl /etc/passwd | sed '/root/d'2 bin:x:1:1:bin:/bin:/sbin/nologin3 daemon:x:2:2:daemon:/sbin:/sbin/nologin4 adm:x:3:4:adm:/var/adm:/sbin/nologin5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin6 sync:x:5:0:sync:/sbin:/bin/sync7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown8 halt:x:7:0:halt:/sbin:/sbin/halt9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin11 games:x:12:100:games:/usr/games:/sbin/nologin12 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin13 nobody:x:99:99:Nobody:/:/sbin/nologin14 systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin15 dbus:x:81:81:System message bus:/:/sbin/nologin16 polkitd:x:999:998:User for polkitd:/:/sbin/nologin17 sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin18 postfix:x:89:89::/var/spool/postfix:/sbin/nologin
数据的搜寻并执行命令
搜索/etc/passwd,找到root对应的行,执行后面花括号中的一组命令,每个命令之间用分号分隔,这里把bash替换为blueshell,再输出这行。
[root@localhost ~]# nl /etc/passwd | sed -n '/root/{s/bash/blueshell/;p;q}'1 root:x:0:0:root:/root:/bin/blueshell
数据的搜寻并替换
除了整行的处理模式之外, sed 还可以用行为单位进行部分数据的搜寻并取代
sed 's/要被取代的字串/新的字串/g'
查询IP
原始信息[root@localhost ~]# ifconfigens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 192.168.91.128 netmask 255.255.255.0 broadcast 192.168.91.255inet6 fe80::2de4:b37a:36e9:ae2e prefixlen 64 scopeid 0x20<link>ether 00:0c:29:d3:76:83 txqueuelen 1000 (Ethernet)RX packets 33461 bytes 32133707 (30.6 MiB)RX errors 0 dropped 0 overruns 0 frame 0TX packets 11322 bytes 1300148 (1.2 MiB)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536inet 127.0.0.1 netmask 255.0.0.0inet6 ::1 prefixlen 128 scopeid 0x10<host>loop txqueuelen 1000 (Local Loopback)RX packets 10 bytes 697 (697.0 B)RX errors 0 dropped 0 overruns 0 frame 0TX packets 10 bytes 697 (697.0 B)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
取有IP地址那一行
[root@localhost ~]# ifconfig | sed -n '/netmask/p'inet 192.168.91.128 netmask 255.255.255.0 broadcast 192.168.91.255inet 127.0.0.1 netmask 255.0.0.0
删除IP地址前面和后面的东西
[root@localhost ~]# ifconfig | sed -n '/netmask/p' | sed 's/^.*inet //g' | sed 's/netmask.*$//g'192.168.91.128127.0.0.1
取第一行
[root@localhost ~]# ifconfig | sed -n '/netmask/p' | sed 's/^.*inet //g' |sed 's/ netmask.*$//g' | sed -n '1p'192.168.91.128
ps:可以在末尾加g替换每一个匹配的关键字,否则只替换每行的第一个
多点编辑
一条sed命令,删除/etc/passwd第三行到末尾的数据,并把bash替换为blueshell
[root@localhost ~]# nl /etc/passwd | sed -e '3,$d' -e 's/bash/blueshell/'1 root:x:0:0:root:/root:/bin/blueshell2 bin:x:1:1:bin:/bin:/sbin/nologin
-e表示多点编辑,第一个编辑命令删除/etc/passwd第三行到末尾的数据,第二条命令搜索bash替换为blueshell。
直接修改文件内容(危险动作)
[root@localhost ~]# cat testline one.line two.line three.line four.line five.
[root@localhost ~]# sed -i 's/\.$/\!/g' test[root@localhost ~]# cat testline one!line two!line three!line four!line five!
利用sed在最后一行添加“# test”
[root@localhost ~]# sed -i '$a # test' test[root@localhost ~]# cat testline one!line two!line three!line four!line five!# test
awk
使用方法
awk '{pattern + action}' {filenames}
其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。花括号{}不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。 pattern就是要表示的正则表达式,用斜杠括起来。
awk语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,awk抽取信息后,才能进行其他文本操作。完整的awk脚本通常用来格式化文本文件中的信息。
通常,awk是以文件的一行为处理单位的。awk每接收文件的一行,然后执行相应的命令,来处理文本。
awk原理
[root@localhost ~]# awk '{print $0}' /etc/passwd
执行 awk 时,它依次对/etc/passwd 中的每一行执行 print 命令。
“$0”是一条记录,”$n”是该记录第n个字段。
[root@server1 ~]# awk -F":" '{print $1}' /etc/passwdrootbindaemonadmlpsyncshutdownhaltoperatorgamesftpnobodysystemd-networkdbuspolkitdsshdpostfixchronyzhangsancentos[root@server1 ~]# awk -F':' '{print $1 $3}' /etc/passwdroot0bin1daemon2adm3lp4sync5shutdown6halt7mail8operator11games12ftp14nobody99systemd-network192dbus81polkitd999sshd74postfix89chrony998zhangsan1000centos1001[root@server1 ~]# awk -F":" '{print $1" " $3}' /etc/passwdroot 0bin 1daemon 2adm 3lp 4sync 5shutdown 6halt 7mail 8operator 11games 12ftp 14nobody 99systemd-network 192dbus 81polkitd 999sshd 74postfix 89chrony 998zhangsan 1000centos 1001[root@server1 ~]# awk -F":" '{print "username:"$1"\t\tuid:" $3}' /etc/passwdusername:root uid:0username:bin uid:1username:daemon uid:2username:adm uid:3username:lp uid:4username:sync uid:5username:shutdown uid:6username:halt uid:7username:mail uid:8username:operator uid:11username:games uid:12username:ftp uid:14username:nobody uid:99username:systemd-network uid:192username:dbus uid:81username:polkitd uid:999username:sshd uid:74username:postfix uid:89username:chrony uid:998username:zhangsan uid:1000username:centos uid:1001
-F参数:指定分隔符,可指定一个或多个
print 后面做字符串的拼接
实例一:只查看test.txt文件(100行)内第20到第30行的内容(企业面试)
创建文件
[root@server1 ~]# seq 1 100 > test.txt
[root@server1 ~]# awk '{if (NR>=20 && NR<=30) print $0}' test.txt2021222324252627282930
实例二
已知test.txt文件内容为
[root@server1 ~]# cat test.txtI am aaron, my qq is 1234567
请从该文件中过滤出 ‘aaron’ 字符串与 ‘1234567’,最后输出的结果为:aaron 1234567
[root@server1 ~]# awk -F '[ ,]+' '{print $3 " " $7}' test.txtaaron 1234567
[ ,]+这个是正则表达式,+表示一个或多个,这里表示一个或多个空格或逗号
BEGIN和END模块
实例一:统计/etc/passwd的账户人数
[root@server1 ~]# awk '{count++;print $0;} END{print "user count is",count}' /etc/passwd
count是自定义变量。之前的action{}里都是只有一个print,其实print只是一个语句,而action{}可以有多个语句,以 ‘;’ 号隔开。这里没有初始化count,虽然默认是0,但是妥当的做法还是初始化为0
[root@server1 ~]# awk 'BEGIN{count=0;print"[start] user count is ",count}{count++;print $0} END{print "[end] user count is ",count}' /etc/passwd[start] user count is 0root:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinsync:x:5:0:sync:/sbin:/bin/syncshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/haltmail:x:8:12:mail:/var/spool/mail:/sbin/nologinoperator:x:11:0:operator:/root:/sbin/nologingames:x:12:100:games:/usr/games:/sbin/nologinftp:x:14:50:FTP User:/var/ftp:/sbin/nologinnobody:x:99:99:Nobody:/:/sbin/nologinsystemd-network:x:192:192:systemd Network Management:/:/sbin/nologindbus:x:81:81:System message bus:/:/sbin/nologinpolkitd:x:999:998:User for polkitd:/:/sbin/nologinsshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologinpostfix:x:89:89::/var/spool/postfix:/sbin/nologinchrony:x:998:996::/var/lib/chrony:/sbin/nologinzhangsan:x:1000:1000::/home/zhangsan:/bin/bashcentos:x:1001:2333::/home/centos:/bin/bash[end] user count is 21
实例二:统计某个文件夹下的文件占用的字节数
[root@server1 ~]# ll总用量 136-rw-------. 1 root root 1241 12月 20 15:38 anaconda-ks.cfg-rw-r--r--. 1 root root 87119 5月 26 2016 mha4mysql-manager-0.56-0.el6.noarch.rpm-rw-r--r--. 1 root root 36326 5月 26 2016 mha4mysql-node-0.56-0.el6.noarch.rpm-rw-r--r--. 1 root root 55 4月 11 15:59 test1-rw-r--r--. 1 root root 29 4月 11 21:06 test.txt[root@server1 ~]# ll | awk 'BEGIN{size=0}{size=size+$5} END{print "size is",size}'size is 124770
awk运算符
| 运算符 | 描述 |
|---|---|
| 赋值运算符 | |
| = += -= = /= %= ^= *= | 赋值语句 |
| 逻辑运算符 | |
| || | 逻辑或 |
| && | 逻辑与 |
| 正则运算符 | |
| ~ !~ | 匹配正则表达式和不匹配正则表达式 |
| 关系运算符 | |
| < <= > >= != == | 关系运算符 |
| 算术运算符 | |
| + - | 加,减 |
| * / % | 乘,除与求余 |
| + - ! | 一元加,减和逻辑非 |
| ^ * | 求幂 |
| ++ — | 增加或减少,作为前缀或后缀 |
| 其他运算符 | |
| $ | 字段引用 |
| 空格 | 字符串链接符 |
| ?: | 三目运算符 |
| ln | 数组中是否存在某键值 |
awk 赋值运算符:a+=5;等价于a=a+5;其他同类
[root@server1 ~]# awk 'BEGIN{a=5;a+=5;print a}'10
awk逻辑运算符:判断表达式 a>2&&b>1为真还是为假,后面的表达式同理
[root@server1 ~]# awk 'BEGIN{a=1;b=2;print (a>2&&b>1,a=1||b>1)}'0 1
awk正则运算符:
[root@node-1 ~]# awk 'BEGIN{a="100testaa";if(a~/100/) {print "OK"}}'OK[root@node-1 ~]# echo | awk 'BEGIN{a="100testaa"}a~/100/{print "OK"}'OK
关系运算符:
如: > < 可以作为字符串比较,也可以用作数值比较,关键看操作数如果是字符串就会转换为字符串比
较。两个都为数字才转为数值比较。字符串比较:按照ascii码顺序比较。
[root@node-1 ~]# awk 'BEGIN{a="11";if(a>=9){print"OK"}}'[root@node-1 ~]# awk 'BEGIN{a=11;if(a>=9){print"OK"}}'OK[root@node-1 ~]# awk 'BEGIN{a;if(a>=b){print"OK"}}'OK
awk 算术运算符:
说明,所有用作算术运算符进行操作,操作数自动转为数值,所有非数值都变为0。
[root@node-1 ~]# awk 'BEGIN{a="b";print a++,++a}'0 2[root@node-1 ~]# awk 'BEGIN{a="20b4";print a++,++a}'20 22
这里的a++ , ++a与javascript语言一样:a++是先赋值加++;++a是先++再赋值
三目运算符 ?:
[root@node-1 ~]# awk 'BEGIN{a="b";print a=="b"?"ok":"err"}'ok[root@node-1 ~]# awk 'BEGIN{a="b";print a=="c"?"ok":"err"}'err
常用awk内置变量
| 变量名 | 属性 |
|---|---|
| $0 | 当前记录 |
| $1~$n | 当前记录的第1~n个字段 |
| FS | 输入字段分隔符,默认是空格 |
| RS | 输入记录分隔符,默认是换行符 |
| NF | 当前记录字段的个数,就是有多少列 |
| NR | 已读出的记录数,就是行号,从1开始 |
| OFS | 输出字段分隔符,默认空格 |
| ORS | 输出记录分隔符,默认换行 |
注:内置变量很多,参阅相关资料
字段分隔符 FS
FS=”\t” 表示一个或多个 Tab 分隔
[root@node-1 ~]# cat tab.txtaa bb cc[root@node-1 ~]# awk 'BEGIN{FS="\t+"}{print $1,$2,$3}' tab.txtaa bb cc
FS=”[[:space:]+]” 一个或多个空白空格,默认的,匹配到不符合的就停止
[root@node-1 ~]# awk -F [[:space:]+] '{print $1,$2,$3,$4,$5}' tab.txtaa bb cc[root@node-1 ~]# awk -F [[:space:]+] '{print $1,$2}' tab.txtaa bb
FS=”[“ “:]+” 以一个或多个空格或:分隔
[root@node-1 ~]# awk -F [" ":]+ '{print $1,$2,$3}' hello.txtroot x 0
字段数量 NF :显示满足用:分割,并且有8个字段的
[root@node-1 ~]# awk -F ":" 'NF==8{print $0}' hello.txtbin:x:1:1:bin:/bin:/sbin/nologin:888
记录数量NR
[root@node-1 ~]# ifconfig br0 | awk -F [" ":]+ 'NR==2{print $3}'192.168.0.241
RS 记录分隔符变量
将 FS 设置成”\n”告诉 awk 每个字段都占据一行。通过将 RS 设置成””,还会告诉 awk每个地址记录都由空白行分隔。
[root@node-1 ~]# cat awk.txt#!/bin/awkBEGIN {FS="\n"RS=""}{print $1","$2","$3}[root@node-1 ~]# awk -f awk.txt recode.txt
在””分割符之内,符合\n分割的会被打印出来
OFS 输出字段分隔符
[root@node-1 ~]# awk 'BEGIN{FS=":";OFS="#"}{print $1,$2,$3}' hello.txtroot#x#0bin#x#1
ORS 输出记录分隔符
[root@node-1 ~]# cat awk.txt#!/bin/awkBEGIN {FS="\n"RS=""ORS="\n\n"}{print $1","$2","$3}[root@node-1 ~]# awk -f awk.txt recode.txtJimmy the Weasel,100 Pleasant Drive,San Francisco,CA 123456Big Tony,200 Incognito Ave.,Suburbia,WA 64890
awk正则
| 元字符 | 功能 | 示例 | 解释 |
|---|---|---|---|
| ^ | 首行定位符 | /^root/ | 匹配所有以root开头的行 |
| $ | 行尾定位符 | /root$/ | 匹配所有以root结尾的行 |
| . | 匹配任意单个字符 | /r..t/ | 匹配字母r,然后两个字符,再以t结尾的行 |
| * | 匹配0个或多个前导字符(包括回车) | /a*ool/ | 匹配0个或多个a之后紧跟着ool的行,比如ool,aaaaool等 |
| + | 匹配1个或多个前导字符 | /a+b/ | ab,aaab |
| ? | 匹配1个或0个前导字符 | /a?b/ | b,ab |
| [] | 匹配字符组内的任意一个字符 | /^[abc]/ | 匹配以a或b或c开头的行 |
| [^] | 匹配不在指定字符组内任意一个字符 | /\^[\^abc]/ | 匹配不以字母a或b或c开头的行 |
| () | 子表达式组合 | /(rool)+/ | 表示一个或多个rool组合,当有一些字符需要组合时,使用括号括起来 |
| | | 或者 | /(root)\|b/ | 匹配root或者b的行 |
| \ | 转义字符 | /a\/\// | 匹配a// |
| ~ !~ | 匹配 不匹配条件语句 | $1~/root/ | 匹配第一个字段包含root的所有记录 |
| x{m} x{m,} x{m,n} |
x重复m次 x重复至少m次 x重复至少m次,但是不超过n次 |
/(root){3}/ /(root){3,}/ /(root){3,6}/ |
root重复三次 root至少重复三次 root至少重复三次,至多重复6次 |
应用
规则表达式
awk '/REG/{action} ' file,/REG/为正则表达式,可以将满足条件的记录送入到 action 进行处理[root@server1 ~]# awk '/root/{print$0}' /etc/passwdroot:x:0:0:root:/root:/bin/bashoperator:x:11:0:operator:/root:/sbin/nologin[root@server1 ~]# awk -F":" '$5~/root/{print$0}' /etc/passwdroot:x:0:0:root:/root:/bin/bash
布尔表达式
awk '布尔表达式{action}' file仅当对前面的布尔表达式求值为真时, awk 才执行代码块。[root@server1 ~]# awk -F":" '$5=="root"{print$0}' /etc/passwdroot:x:0:0:root:/root:/bin/bash[root@server1 ~]# awk -F: '($1=="root")&&($5=="root"){print$0}' /etc/passwdroot:x:0:0:root:/root:/bin/bash
awk的if、循环和数组
if
使用 if 语句还可以将代码:{if ($1=="foo"){if ($2=="foo"){print"uno"}else{print"one"}}elseif($1=="bar"){print "two"}else{print"three"}}
转换成! /matchme/ { print $1 $3 $4 }
{if ( $0 !~ /matchme/ ) {print $1 $3 $4}}
循环while/for
我们已经看到了 awk 的 while 循环结构,它等同于相应的 C 语言 while 循环。 awk 还有”do…while”循环,它在代码块结尾处对条件求值,而不像标准 while 循环那样在开始处求值。
它类似于其它语言中的”repeat…until”循环。以下是一个示例:
do…while示例
{count=1do {print "I get printed at least once no matter what"} while ( count !=1 )}
与一般的 while 循环不同,由于在代码块之后对条件求值, “do…while”循环永远都至少执行一次。换句话说,当第一次遇到普通 while 循环时,如果条件为假,将永远不执行该循环。
for循环
awk 允许创建 for 循环,for循环的执行顺序为initial assignment,然后循环执行code block -> increment -> comparison
for ( initial assignment; comparison; increment ) {code block}
以下是一个简短示例
for ( x=1;x<=4;x++ ) {print "iteration", x}
break 和 continue
此外,如同 C 语言一样, awk 提供了 break 和 continue 语句。使用这些语句可以更好地控制 awk 的
循环结构。
#!/bin/awkBEGIN{x=1while(1) {print "iteration",xif ( x==10 ){break}x++}}
continue 语句补充了 break
x=1while (1) {if ( x==4 ) {x++continue}print "iteration", xif ( x>20 ) {break}x++}
continue在for中使用
#!/bin/awkBEGIN{for (x=1;x<=21;x++){if (x==4){continue}print "iteration",x}}
数组
AWK 中的数组都是关联数组,数字索引也会转变为字符串索引
#!/bin/awkBEGIN{cities[1]="beijing"cities[2]="shanghai"cities["three"]="guangzhou"for( c in cities) {print cities[c]}print cities[1]print cities["1"]print cities["three"]}[root@server1 ~]# awk -f for.shguangzhoubeijingshanghaibeijingbeijingguangzhou
用 awk 中查看服务器连接状态并汇总
[root@server1 ~]# netstat -an|awk '/^tcp/{++s[$NF]}END{for(a in s)print a,s[a]}'LISTEN 4ESTABLISHED 1
常用字符串函数
| 函数 | 说明 |
|---|---|
| gsub(Ere,Repl,[ln]) | 除了正则表达式所有具体值被替代,它和sub函数完全一样执行 |
| sub(Ere,Repl,[ln]) | 用Repl参数指定的字符串替换ln参数指定的字符串中的由Ere参数指定的扩展正则表达式的第一个具体值。sub函数返回替换的数量。 出现在Repl参数指定的字符串中的&(和符号)由ln参数指定的与Ere参数指定的扩展正则表达式匹配的字符串替换。如果未指定ln参数,缺省值是整个记录($0记录变量) |
| index(String1,String2) | 在由String1参数指定的字符串中(其中有出现String2指定的参数),返回位置,从1开始编号。如果String2参数不在String1参数中出现,则返回0(零)。 |
| length[(String)] | 返回String参数指定的字符串的长度(字符形式)。如果未给出String参数,则返回整个记录的长度($0记录变量)。 |
| blength[(String)] | 返回String参数指定的字符串长度(以字节为单位)。如果未给出String参数,则返回整个记录的长度($0记录变量)。 |
| substr(String,M,[N]) | 返回具有N参数指定的字符数量子串。子串从String参数指定的字符串获取,其字符串以M指定的位置开始。M参数指定为将Stirng参数中的第一个字符作为编号1。如果未指定N参数,则子串的长度将是M参数指定的位置到String参数的末尾的长度 |
| match(String,Ere) | 在String参数指定的字符串中返回位置,从1开始编号,如果Ere参数不出现,则返回0 |
| split(String,A,[Ere]) | 将String参数指定的参数分割成数组元素A[1]、A[2]…A[n],并返回n的变量值。此分隔可以通过Ere参数指定的扩展正则表达式进行,或用当前字段分隔符(FS特殊变量来进行,如果没有给出Ere参数)。除非上下文指明特殊元素还应具有一个数字值,否则A数组中的元素用字符串值来创建 |
| tolower(String) | 返回String参数指定的字符串,字符串中每个大写参数转换为小写。 |
| toupper(String) | 返回String参数指定的字符串,字符串中每个小写参数转换为大写。 |
| sprintf(Format,Expr,Expr,…) | 根据Format参数指定的printf子例程格式字符串来格式化Expr参数指定的表达式,并返回最后生成的字符串。 |
- 字符串函数应用
在 info 中查找满足正则表达式, /[0-9]+/ 用”!”替换,并且替换后的值,赋值给 info
[root@node-1 ~]# awk 'BEGIN{info="this is a test2010test!";gsub(/[0-9]+/,"!",info);print info}'this is a test!test!
如果查找到数字则匹配成功返回 ok,否则失败,返回未找到
[root@node-1 ~]# awk 'BEGIN{info="this is a test2010test!";printindex(info,"test")?"ok":"no found";}'ok
从第 4 个 字符开始,截取 10 个长度字符串
[root@node-1 ~]# awk 'BEGIN{info="this is a test2010test!";printsubstr(info,4,10);}'s is a tes
分割 info,动态创建数组 tA,awk for …in 循环,是一个无序的循环。 并不是从数组下标1…n 开始、
[root@node-1 ~]# awk 'BEGIN{info="this is a test";split(info,tA," ");printlength(tA);for(k in tA){print k,tA[k];}}'
