文本编辑器
正则表达式
REGEXP: Regular Expressions,由一类特殊字符及文本字符所编写的模式,其中有些字符(元字符)不表示字符字面意义,而表示控制或通配的功能,类似于增强版的通配符功能,但与通配符不同,通配符功能是用来处理文件名,而正则表达式是处理文本内容中字符。
正则表达式被很多程序和开发语言所广泛支持:vim, less,grep,sed,awk, nginx,mysql 等
主要用来匹配字符串(命令结果,文本内容),
通配符匹配文件(而且是已存在的文件)
-
基本正则表达式
-
扩展正则表达式
可以使用
man 7 regex
可以使用 man手册帮助
元字符(字符匹配)
元字符:
. 匹配任意单个字符,可以是一个汉字
[] 匹配指定范围内的任意单个字符,示例:[zhou] [0-9] [] [a-zA-Z] [[:alpha:]] [0-9a-zA-Z]= [:alnum:]
[^] 匹配指定范围外的任意单个字符,示例:[^zhou] [^a.z] [a.z]
[:alnum:] 字母和数字
[:alpha:] 代表任何英文大小写字符,亦即 A-Z, a-z
[:lower:] 小写字母,示例:[[:lower:]],相当于[a-z]
[:upper:] 大写字母
[:blank:] 空白字符(空格和制表符)
[:space:] 包括空格、制表符 (水平和垂直)、换行符、回车符等各种类型的空白,比[:blank:]包含的范围广
[:cntrl:] 不可打印的控制字符(退格、删除、警铃...)
[:digit:] 十进制数字
[:xdigit:]十六进制数字
[:graph:] 可打印的非空白字符
[:print:] 可打印字符
[:punct:] 标点符号
\w #匹配单词构成部分,等价于[_[:alnum:]]
\W #匹配非单词构成部分,等价于[^_[:alnum:]]
\S #匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\s #匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。注意Unicode 正则表达式会匹配全角空格符
元字符点(.)
[root@localhost ~]#ls /etc/|grep rc[.0-6]
#此处的点代表字符
rc0.d
rc1.d
rc2.d
rc3.d
rc4.d
rc5.d
rc6.d
rc.d
rc.local
[root@localhost ~]#ls /etc/ | grep 'rc\.'
#点值表示点需要转义
rc.d
rc.local
[root@localhost ~]# grep r..t /etc/passwd
#r..t ..代表任意两个字符
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
[root@localhost ~]# echo abc |grep a.c
#表示原来的点需要加\转义
abc
[root@localhost ~]# echo abc |grep a\.c
#不加引号有时匹配会有出入
abc
[root@localhost ~]# echo abc |grep 'a\.c'
#标准格式需要加'' 或者""
[root@localhost ~]# ls |grep '[zhou].txt'
#匹配[]中任意一个字符
h.txt
o.txt
u.txt
z.txt
[root@localhost ~]# ls [a-d].txt
#通配符
a.txt A.txt b.txt B.txt c.txt C.txt d.txt
[root@localhost ~]# ls |grep '[a-d].txt'
#真正的小写在正则表达式中
a.txt
b.txt
c.txt
d.txt
[root@localhost ~]# ls |grep '[^a-z].txt'
#显示非小写字母
A.txt
B.txt
[root@localhost ~]# ls |grep '[^a.z].txt'
#[]里就是本意不需要转义
space空格
[root@localhost ky15]#grep [[:space:]] zhen.txt
hhh
jj l
kkk
[root@localhost ky15]#grep [[:space:]] zhen.txt |cat -A
hhh $
jj^I^Il$
kkk $
[root@localhost ~]#ls /etc/ |grep "rc[.0-6]" rc. rc0 rc1 rc2 rc3 rc6
[root@localhost ~]#ls /etc/ |grep "rc[.0-6]."
表示次数 表示一个qq 号码
* #匹配前面的字符任意次,包括0次,贪婪模式:尽可能长的匹配
.* #任意长度的任意字符 不包括0次
\? #匹配其前面的字符出现0次或1次,即:可有可无
\+ #匹配其前面的字符出现最少1次,即:肯定有且 >=1 次
\{n\} #匹配前面的字符n次
\{m,n\} #匹配前面的字符至少m次,至多n次
\{,n\} #匹配前面的字符至多n次,<=n
\{n,\} #匹配前面的字符至少n次
ifconfig ens33|grep netmask|grep -o
[0-9] [0 1 2 3 4 5 6 7 8 9]
ifconfig ens33|grep netmask|grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+'|head -n1
ifconfig ens33|grep netmask|grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'|head -n1
举例:
[root@localhost ~]# echo google |grep 'go\{2\}gle'
#带表前面的o出现2次
google
[root@localhost ~]# echo gooooogle |grep 'go\{2,\}gle'
#带表前面的o出现2次以上
gooooogle
[root@localhost ~]# echo gooooogle |grep 'go\{2,5\}gle'
#带表前面的o出现2次以上5次以下
gooooogle
[root@localhost ~]# echo goooooogle |grep 'go\{2,5\}gle'
[root@localhost ~]#
[root@localhost ~]# echo goooooogle |grep 'go*gle'
#表示0次到任意次
goooooogle
[root@localhost ~]# echo ggle |grep "go*gle"
ggle
[root@localhost ~]# echo gggle |grep "go*gle"
#grep 包含最前面的g不匹配
gggle
[root@localhost ~]# echo gdadadadgle |grep "g.*gle"
#.*代表任意匹配所有
gdadadadgle
[root@localhost ~]# echo ggle |grep "go\?gle"
# \?一次或者0次
ggle
[root@localhost ~]# echo gogle |grep "go\?gle"
gogle
[root@[root@localhost ~]# echo google |grep "go\+gle"
#一个以上
google
[root@localhost ~]# echo gogle |grep "go\+gle"
gogle
[root@localhost ~]# echo ggle |grep "go\+gle"
[root@localhost ~]# echo google |grep "go\?gle"
[root@localhost ~]#echo abc|grep "[abc]\{3\}"
#需要加引号
#他的 匹配思路是 [abc]\{3\} 在匹配abc的时候
#第一轮 看 首字母 是否有abc中的一个, 第二轮也是看是否有abc中的一个 第三轮也是看是否有abc中的一个
位置锚定
^ #行首锚定, 用于模式的最左侧
$ #行尾锚定,用于模式的最右侧
^PATTERN$ #用于模式匹配整行 (单独一行 只有root)
^$ #空行
^[[:space:]]*$ # 空白行 tab 换行 回车
\< 或 \b #词首锚定,用于单词模式的左侧(连续的数字,字母,下划线都算单词内部)
\> 或 \b #词尾锚定,用于单词模式的右侧
\<PATTERN\> #匹配整个单词
\root\
例子:
思考过滤出不是已#号开头的非空行
[root@localhost ~]#grep "^[^#]" /etc/fstab
[root@localhost data]#grep "^google$" test.txt
#只匹配google 这个字符
[root@localhost ~]#grep "^[[:space:]]*$" /etc/fstab
[root@localhost ~]#echo hello-123 |grep "\<123"
#除了 字母 数字 下划线其他都算 单词的分隔符
hello-123
[root@localhost ~]#echo hello 123 |grep "\<123"
hello 123
分组或其他
分组:( ) 将多个字符捆绑在一起,当作一个整体处理,如:(root)+
后向引用:分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名
方式为: \1, \2, \3, ... 分组
\1 表示从左侧起第一个左括号以及与之匹配右括号之间的模式所匹配到的字符
或者
或者
或者:\|
示例
[root@localhost ~]#echo abccc |grep "abc\{3\}"
abccc
[root@localhost ~]#echo abcabcabc |grep "\(abc\)\{3\}"
#分组 匹配abc
abcabcabc
[root@localhost ~]#echo 1abc |grep "1\|2abc"
#只匹配了1
1abc
[root@localhost ~]#echo 1abc |grep "\(1\|2\)abc"
#1abc或者2abc
1abc
[root@localhost ~]#ifconfig ens33|grep netmask|grep -o '\([0-9]\{1,3\}\.\)\{3\}[0-9]\{3\}'|head -1
192.168.91.100
[root@localhost ~] ens33 |grep netmask|grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}'|head -1
[root@localhost ky15]#ifconfig ens33 |grep netmask|grep -Eo '([0-9]{1,3}.){4}'
扩展正则表达式(表示字符相差不大)
grep -E
egrep 默认使用的 是扩张正则
表示次数
* 匹配前面字符任意次
? 0或1次
+ 1次或多次
{n} 匹配n次
{m,n} 至少m,至多n次
{,n} #匹配前面的字符至多n次,<=n,n可以为0
{n,} #匹配前面的字符至少n次,<=n,n可以为0
表示分组
() 分组
分组:() 将多个字符捆绑在一起,当作一个整体处理,如:\(root\)+
后向引用:\1, \2, ...
| 或者
a|b #a或b
C|cat #C或cat
(C|c)at #Cat或cat
例:
1表示qq号
[root@localhost ~]# grep -E "\b[0-9]{6,12}\b"
#6到12位的连续数字
- 表示邮箱
[root@localhost ~]# grep -E "[[:alnum:]_-]+@[[:alnum:]_]+\.[[:alnum:]_]+"
#数字字母_-1位以上加上@后面跟数字字母1位以上.数字字母1位以上
3.表示手机号
[root@localhost ~]# grep -E "\b1[3456789][0-9]{9}\b"
#1开头第二位为(3,4,5,6,7,8,9)的11位的连续数字
文本编辑工具
grep
grep [选项]… 查找条件 目标文件
选项:
-color=auto #对匹配到的文本着色显示
-m # 匹配#次后停止 匹配到 #行停止
grep -m 1 root /etc/passwd #多个匹配只取第一个
-v 显示不被pattern匹配到的行,即取反
grep -Ev '^[[:space:]]*#|^$' /etc/fstab
-i 忽略字符大小写
-n 显示匹配的行号
-c 统计匹配的行数
grep -c root /etc/passwd #统计匹配到的行数
-o 仅显示匹配到的字符串
-q 静默模式,不输出任何信息 写脚本
-A # after, 后#行
grep -A3 root /etc/passwd #匹配到的行后3行业显示出来
-B # before, 前#行
-C # context, 前后各#行
-e 实现多个选项间的逻辑or关系,如:grep –e ‘cat ' -e ‘dog' file
grep -e root -e bash /etc/passwd #包含root或者包含bash 的行
grep -E root|bash /etc/passwd
-w 匹配整个单词
grep -w root /etc/passwd
useradd rooter
-E 使用ERE,相当于egrep
-F 不支持正则表达式,相当于fgrep
-f file 根据模式文件,处理两个文件相同内容 把第一个文件作为匹配条件 grep -f a b
-r 递归目录,但不处理软链接 开始搜索目录
-R 递归目录,但处理软链接
grep root /etc/passwd
grep "USER" /etc/passwd
grep 'USER' /etc/passwd
grep whoami /etc/passwd
[root@test1 opt]# cat 123.txt |grep -v '^$' >test.txt //将非空行写入到test.txt文件
[root@test1 opt]# grep "^b" 123.txt //过滤已b开头
[root@test1 opt]#grep '/$' 123.txt //过滤已/结尾
[root@test1 opt]# grep -v "^$" 123.txt //过滤非空行3 备份与
[root@localhost yum.repos.d]# ifconfig ens33 |grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+"
192.168.91.100
255.255.255.0
192.168.91.255
[root@localhost yum.repos.d]# ifconfig ens33 |grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+"|head -1
192.168.91.100
###面试题 统计当前主机的连接状态
[root@localhost ~]# ss -nta | grep -v '^State' |cut -d" " -f1|sort |uniq -c
3 ESTAB
17 LISTEN
#####统计当前连接主机数
[root@localhost ~]#ss -nt |tr -s " "|cut -d " " -f5|cut -d ":" -f1 |sort|uniq -c
3 192.168.91.1
1 192.168.91.101
1 Address
sed
sed 即 Stream EDitor,是行编辑器
sed [选项]... {脚本(如果没有其他脚本)} [输入文件]...
Sed是从文件或管道中读取一行,处理一行,输出一行;再读取一行,再处理一行,再输出一行,直到最后一行。每当处理一行时,把当前处理的行存储在临时缓冲区中,称为模式空间(PatternSpace),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。一次处理一行的设计模式使得sed性能很高,sed在读取大文件时不会出现卡顿的现象。如果使用vi命令打开几十M上百M的文件,明显会出现有卡顿的现象,这是因为vi命令打开文件是一次性将文件加载到内存,然后再打开。Sed就避免了这种情况,一行一行的处理,打开速度非常快,执行速度也很快
基本用法
sed [option]... 'script;script;...' [input file...]
选项 自身脚本语法 支持标准输入管道
常用选项:
-n 不输出模式空间内容到屏幕,即不自动打印
-e 多点编辑
#[root@www data]#sed -n -e '/^r/p' -e'/^b/p' /etc/passwd
-f FILE 从指定文件中读取编辑脚本
-r, -E 使用扩展正则表达式
-i.bak 备份文件并原处编辑
sed -r 基础正则
#说明:
-ir 不支持
-i -r 支持
-ri 支持
-ni 会清空文件
基本用法
[root@localhost ~]#sed
#提示错误
[root@localhost ~]#sed ' '
####默认将输入内容打印出来,系统自带自动打印
aaa
aaa
dd
dd
dd
dd
[root@localhost ~]#sed '' /etc/fstab
####查看文件内容
#
# /etc/fstab
# Created by anaconda on Fri Aug 6 20:57:12 2021
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/centos-root / xfs defaults 0 0
UUID=e9364e9b-a85b-49d7-9652-3a56202e14c8 /boot xfs defaults 0 0
/dev/mapper/centos-swap swap swap defaults 0 0
[root@localhost ~]#sed '' </etc/fstab
####支持重定向
#
# /etc/fstab
# Created by anaconda on Fri Aug 6 20:57:12 2021
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/centos-root / xfs defaults 0 0
UUID=e9364e9b-a85b-49d7-9652-3a56202e14c8 /boot xfs defaults 0 0
/dev/mapper/centos-swap swap swap defaults 0 0
[root@localhost ~]#cat /etc/issue |sed ''
#####也支持管道符
\S
Kernel \r on an \m
脚本格式
单引号中间需要写脚本;脚本格式如下
'地址+命令'组成
1. 不给地址:对全文进行处理(比如行号)
2. 单地址:
#:指定的行,$:最后一行
/pattern/:被此处模式所能够匹配到的每一行,正则表达式
3. 地址范围:
#,# #从#行到第#行,3,6 从第3行到第6行
#,+# #从#行到+#行,3,+4 表示从3行到第7行
/pat1/,/pat2/ 第一个正则表达式 到 第二个正则表达式之间的行
#,/pat/ 从#号行为开始找到 pat为止 3 , /^r/
/pat/,# 找到#号个pat为止
4. 步进:~
1~2 奇数行
2~2 偶数行
sed -n 'n;p' testfile1 #打印偶数行
sed -n '2,${n;p}' testfile1
命令
p 打印当前模式空间内容,追加到默认输出之后
Ip 忽略大小写输出
d 删除模式空间匹配的行,并立即启用下一轮循环
a [\]text 在指定行后面追加文本,支持使用\n实现多行追加
i [\]text 在行前面插入文本
c [\]text 替换行为单行或多行文本
w file 保存模式匹配的行至指定文件 seq 10 |sed -n '2wa.txt'
r file 读取指定文件的文本至模式空间中匹配到的行后 seq 10|sed '2r /etc/issue'
= 为模式空间中的行打印行号 sed '2=' /etc/passwd sed -n -e '=;p' /etc/passwd
! 模式空间中匹配行取反处理seq 10 |sed -n '1~2!p'
q 结束或退出sed seq 10 | sed '3q'
[root@localhost ~]#seq 10 | sed 'p'
#带有自动打印功能,p又再打印一遍
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
[root@localhost ~]#seq 10 | sed -n 'p'
#-n 选项关闭自动打印功能
1
2
3
4
5
6
7
8
9
10
#如何加入地址
直接显示第三行
[root@localhost ~]#seq 10 | sed -n '3p'
#直接显示第3行
3
[root@localhost ~]#ifconfig ens33|sed -n 2p
#直接显示第二行内容
inet 192.168.91.100 netmask 255.255.255.0 broadcast 192.168.91.255
[root@localhost ~]#seq 10 |sed -n '$p'
#最后一行
10
###还支持正则表达式
[root@localhost ~]#sed '/root/p' /etc/passwd
###自动打印需要关闭否则会全部打印
root:x:0:0:root:/root:/bin/bash
省略多行。。。。。。。。
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
[root@localhost ~]#sed -n '/root/p' /etc/passwd
##将包含root的行打印出来 /root(需要匹配的内容)/p(打印) 文件名
###与 grep root /etc/passwd 功能相同
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
####如何显示范围 行号,行号
[root@localhost ~]#seq 10|sed -n '3,6p'
###显示范围
3
4
5
6
[root@localhost ~]#seq 10|sed -n '3,+4p'
##3 往后加4行
3
4
5
6
7
###还可以匹配 两个正则表达式之间的行
举例子
[root@localhost ~]#cat /etc/passwd
###我想显示b开头 和f开头中间的行
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
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
[root@localhost ~]#sed -n '/^b/,/^f/p' /etc/passwd
### 基本格式 '/表达式1/,/表达式2/p' (不要忘记打印)p 文件名
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
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
####匹配方式 如果有多个复合条件的表达式
先开始找b开头一直找到f开头
然后再重新找b开头,一找到f开头,没有f开头就全显示
重复循环
######面试题,显示几点到几点分的日志#######
让你查找几点几分到几点几分之间的日志
[root@localhost ~]#sed -n '/2018:08:09/,/2018:09:42:37/p' access_log
sed -n '/2018:11:56:41/,/2018:11:56:44/p' access_log
#奇数偶数表示
[root@localhost ~]#seq 10|sed -n '1~2p'
1
3
5
7
9
[root@localhost ~]#seq 10|sed -n '2~2p'
2
4
6
8
10
[root@localhost ~]#seq 10|sed -n '3~3p'
3
6
9
-d选项删除
[root@localhost ~]#seq 10 |sed '3d'
###将第三行删除
1
2
4
5
6
7
8
9
10
##修改文件内容,常常用于修改配置文件
-i 与 -i.bak
修改文件 修改文件前先备份
[root@localhost ~]#seq 10 >test.txt
[root@localhost ~]#cat test.txt
1
2
3
4
5
6
7
8
9
10
[root@localhost ~]#sed -i '2~2d' test.txt
[root@localhost ~]#cat test.txt
1
3
5
7
9
##### -a 追加
[root@localhost ~]#seq 10 |sed '2ahehe'
###第二行后追加hehe
1
2
hehe
3
4
5
6
7
8
9
10
[root@localhost ky15]#sed -i '2a\\n hehe' seq.txt
#修改文件内部需要多加一个\
[root@localhost ~]#seq 10 |sed '2a \ hehe\nhaha'
###\表示空格 \n 表示换行
1
2
hehe
haha
3
4
5
6
7
8
9
10
[root@localhost ~]#seq 10 |sed '2ihehe'
#第二行前面插入hehe
1
hehe
2
3
4
5
6
7
8
9
10
[root@localhost ~]#seq 10 |sed '2chehe'
#第二行替换成hehe
1
hehe
3
4
5
6
7
8
9
10
[root@localhost ky15]# seq 10 |sed -n '2!p'
#取反
1
3
4
5
6
7
8
9
10
[root@www data]#seq 10 |sed '2r /etc/issue'
1
2
\S
Kernel \r on an \m
3
4
5
6
7
8
9
10
[root@www data]#seq 10 |sed 'w /data/ky21'
[root@www data]#sed '2=' /etc/passwd
root:x:0:0:root:/root:/bin/bash
2
bin:x:1:1:bin:/bin:/sbin/nologin
搜索替代
s/pattern/string/修饰符 查找替换,支持使用其它分隔符,可以是其它形式:s@@@,s###
替换修饰符:
g 行内全局替换
p 显示替换成功的行
w /PATH/FILE 将替换成功的行保存至文件中
I,i 忽略大小写
[root@localhost selinux]#sed -i.bak 's/SELINUX=disabled/SELINUX=enable/' /etc/selinux/config
r/ft er
root er
s//\1/p
inet 192.168.91.100 netmask 255.255.255.0 broadcast 192.168.91.255
s /.* inet (.*) netmask.*/\1/
[root@localhost ~]#sed 's/root/admin/g' /etc/passwd
[root@localhost ~]#sed 's/root/&er/g' /etc/passwd
#&指代之前找到的内容
[root@localhost ~]#echo 123abcxyz |sed -r 's/(123)(abc)(xyz)/\1/'
##分组 s//代表查找替换 ()代表分组 \1 代表留下的组
123
[root@localhost ~]#echo 123xyzabc |sed -r 's/(123)(xyz)(abc)/\1\2/'
123xyz
[root@localhost ~]#echo 123xyzabc |sed -r 's/(123)(xyz)(abc)/\1\3/'
123abc
[root@localhost ~]#ifconfig ens33|sed -rn '2s/.*inet ([0-9.]+) .*/\1/p'
192.168.91.100
[root@localhost selinux]#echo /etc/sysconfig/network-scripts/ifcfg-ens33 |sed -nr 's@^(.*)/([^/]+)@\2@p'
ifcfg-ens33
[root@localhost data]#echo "/etc/sysconfig/network-scripts/ifcfg-ens33"|sed -nr 's#^.*\/(.*)#\1#p'
[root@localhost selinux]#cat 1.txt 2.txt
123
456
123
abc
[root@localhost selinux]#sed -i -e 's/123/cba/' 1.txt -e 's/abc/789/' 2.txt
面试题:提取版本号
[root@localhost /]#cat 1.txt | grep -e "[0-9]\+\."
ant-1.9.7.jar
ant-launcher-1.9.7.jar
antlr-2.7.7.jar
antlr-runtime-3.4.jar
aopalliance-1.0.jar
archaius-core-0.7.6.jar
asm-5.0.4.jar
aspectjweaver-1.9.5.jar
bcpkix-jdk15on-1.64.jar
bcprov-jdk15-1.46.jar
bcprov-jdk15on-1.64.jar
checker-compat-qual-2.5.5.jar
[root@localhost /]#cat 1.txt |sed -r 's/.*-(.*)\.jar/\1/'
1.9.7
1.9.7
2.7.7
3.4
1.0
0.7.6
5.0.4
1.9.5
1.64
1.46
1.64
2.5.5
[root@localhost data]#rev test.txt |awk -F'raj.' '{print $2}'|awk -F'-' '{print $1}'|rev
变量
[root@www data]#name=root
[root@www data]#sed -nr '/$name/p' /etc/passwd
[root@www data]#sed -nr "/$name/p" /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@www data]#sed -nr '/'$name'/p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@www data]#port=8080
[root@www data]#sed -ri 's/^Listen 80/Listen '$port'/' httpd.conf
[root@www data]#sed -ri -e 's/^Listen 80/Listen '$port'/' -e "/^#ServerName/c ServerName `hostname`:$port" httpd.conf
改配置文件
调用变量来改文件
[root@localhost selinux]#name=root
[root@localhost selinux]#sed -nr '/$name/p' /etc/passwd
#使用双引号
[root@localhost selinux]#sed -nr "/$name/p" /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost selinux]#sed -nr '/'$name'/p' /etc/passwd
#变量上家上单引号
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
修改网卡名
ens33
[root@localhost conf]#vim /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
#GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet net.ifnames=0"
#修改这行
GRUB_DISABLE_RECOVERY="true"
sed -ri.bak '/^GRUB_CMDLINE_LINUX/s#(.*)"$#\1 net.ifnames=0"#' /etc/default/grub
sed -ri.bak '/^GRUB_CMDLINE_LINUX/s#"$#net.ifnames=0"#' /etc/default/grub
grub2-mkconfig -o /boot/grub2/grub.cfg
[root@localhost ~]#stat /tmp|sed -n '4p'
权限:(1777/drwxrwxrwt) Uid:( 0/ root) Gid:( 0/ root)
[root@localhost ~]#stat /tmp|sed -rn '4s#.*\(([0-9]+).*#\1#p'
1777
sed的高级用法
sed 中除了模式空间,还另外还支持保持空间(Hold Space),利用此空间,可以将模式空间中的数据,临时保存至保持空间,从而后续接着处理,实现更为强大的功能。
常见的高级命令
P 打印模式空间开端至\n内容,并追加到默认输出之前
h 把模式空间中的内容覆盖至保持空间中
H 把模式空间中的内容追加至保持空间中
g 从保持空间取出数据覆盖至模式空间
G 从保持空间取出内容追加至模式空间
x 把模式空间中的内容与保持空间中的内容进行互换
n 读取匹配到的行的下一行覆盖至模式空间
N 读取匹配到的行的下一行追加至模式空间
d 删除模式空间中的行
D 如果模式空间包含换行符,则删除直到第一个换行符的模式空间中的文本,并不会读取新的输入行,而使
用合成的模式空间重新启动循环。如果模式空间不包含换行符,则会像发出d命令那样启动正常的新循环
例子:
sed -n 'n;p' FILE
seq 10 | sed 'N;s/\n//'
sed '1!G;h;$!d' FILE
seq 10 | sed -n '/3/{g;1!p;};h' #前一行
seq 10 | sed -nr '/3/{n;p}' #后一行
sed 'N;D'FILE
seq 10 |sed '3h;9G;9!d'
sed '$!N;$!D' FILE
sed '$!d' FILE
sed 'G' FILE
sed 'g' FILE
sed '/^$/d;G' FILE
sed 'n;d' FILE
sed -n '1!G;h;$p' FILE
范例: 打印偶数行
seq 10 | sed -n 'n;p'
seq 10 | sed -n '2~2p'
seq 10 | sed '1~2d'
seq 10 | sed -n '1~2!p'
AWK
awk:Aho, Weinberger, Kernighan,报告生成器,格式化文本输出,GNU/Linux发布的AWK目前由自由软件基金会(FSF)进行开发和维护,通常也称它为 GNU AWK
有多种版本:
-
AWK:原先来源于 AT & T 实验室的的AWK
-
NAWK:New awk,AT & T 实验室的AWK的升级版
-
GAWK:即GNU AWK。所有的GNU/Linux发布版都自带GAWK,它与AWK和NAWK完全兼容
GNU AWK 用户手册文档
https://www.gnu.org/software/gawk/manual/gawk.html
gawk:模式扫描和处理语言,可以实现下面功能
vim: 是将整个文件加载到内存中 再进行编辑, 受限你的内存
awk(语言): 读取一行处理一行,
在 Linux/UNIX 系统中,awk 是一个功能强大的编辑工具,逐行读取输入文本,默认以空格或tab键作为分隔符作为分隔,并按模式或者条件执行编辑命令。而awk比较倾向于将一行分成多个字段然后进行处理。AWK信息的读入也是逐行
指定的匹配模式进行查找,对符合条件的内容进行格式化输出或者过滤处理,可以在无交互
的情况下实现相当复杂的文本操作,被广泛应用于 Shell 脚本,完成各种自动化配置任务。
工作原理:
前面提到 sed 命令常用于一整行的处理,而 awk 比较倾向于将一行分成多个“字段”然后再进行处理,且默认情况下字段的分隔符为空格或 tab 键。awk 执行结果可以通过 print 的功能将字段数据打印显示。
格式:
awk [options] 'program' var=value file…
说明:
program通常是被放在单引号中,并可以由三种部分组成
- BEGIN语句块
- 模式匹配的通用语句块
- END语句块
常见选项:
- -F “分隔符” 指明输入时用到的字段分隔符,默认的分隔符是若干个连续空白符
- -v var=value 变量赋值
Program格式:
pattern{action statements;..}
- pattern:决定动作语句何时触发及触发事件,比如:BEGIN,END,正则表达式等
- action statements:对数据进行处理,放在{}内指明,常见:print, printf
- output statements:print,printf
- Expressions:算术,比较表达式等
- Compound statements:组合语句
- Control statements:if, while等
- input statements
第一步:执行BEGIN{action;… }语句块中的语句
第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ action;… }语句块,它逐行扫描文件,
从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
第三步:当读至输入流末尾时,执行END{action;…}语句块
BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中
END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块
pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块
基础用法
print动作
[root@localhost ~]#awk 'patterm{action}'
[root@localhost ~]#awk ''
#什么都不写 空没有效果
[root@localhost ~]#awk '{print}'
##在打印一遍
dd
dd
[root@localhost ~]#awk '{print "hello"}'
#字符串需要添加双引号,单引号已被使用
1
hello
1
hello
[root@localhost ~]#awk '{print "hello"}' < /etc/passwd
[root@localhost ~]#ls | awk '{print "hello"}'
[root@localhost ~]#awk 'BEGIN{print 100+200}'
#运算
300
##############BEGIN ###################
[root@localhost ky15]#awk 'BEGIN {print "hello"}'
#BEGIN比较特殊值打一行 pattern
hello
[root@localhost ~]#awk -F: 'BEGIN {print "hello"} {print $1}' /etc/passwd |head -n3
#先处理BEGIN 中的式子
hello
root
bin
[root@localhost ~]#awk '{print 100}'
#数字不需要
1
100
[root@localhost ~]#awk -F: '{print "root"}' /etc/passwd
#打印root 多少行=passwd里的行数
[root@localhost ky15]#echo {a..b} |awk '{print $1}'
#连续的空白符也可以
a
[root@localhost ky15]#df|awk '{print $5}'
#分区利用率
已用%
8%
0%
0%
1%
0%
4%
0%
1%
[root@localhost ky15]#cat /etc/passwd|awk -F: '{print $1,$3}'
#指定冒号作为分隔符,打印第一列和第三列
[root@localhost ky15]#cat /etc/passwd|awk -F: '{print $1":"$3}'
#用冒号分隔开
[root@localhost ky15]#cat /etc/passwd|awk -F: '{print $1"\t"$3}'
[root@localhost ~]#df|awk -F"( +|%)" '{print $5}'
[root@localhost ky15]#df |awk -F"[[:space:]]+|%" '{print $5}'
[root@localhost ky15]#df |awk -F"[ %]+" '{print $5}'
取 ip地址
[root@localhost ky15]#ifconfig ens33|sed -n '2p' |awk '{print $2}'
[root@localhost ky15]#hostname -I|awk {print $1}
192.168.91.100 192.168.122.1
[root@localhost ~]#wc -l /etc/passwd
45 /etc/passwd
[root@localhost ~]#awk -F: '{print $0}' /etc/passwd
#$0代表全部元素
[root@localhost ~]#awk -F: '{print $1}' /etc/passwd
#代表第一列
[root@localhost ~]#awk -F: '{print $1,$3}' /etc/passwd
#代表第一第三列
[root@localhost ky15]#awk '/^root/{print}' passwd
#已root为开头的行
[root@localhost ky15]#grep -c "/bin/bash$" passwd
#统计当前已/bin/bash结尾的行
2
##### BEGIN{}模式表示,在处理指定的文本前,需要先执行BEGIN模式中的指定动作; awk再处理指定的文本,之后再执行END模式中的指定动作,END{}语句中,一般会放入打印结果等语句。
[root@localhost ky15]#awk 'BEGIN {x=0};/\/bin\/bash$/;{x++};END{print x}' passwd
## 先定义变量
[root@localhost ky15]#awk 'BEGIN {x=0};/\/bin\/bash$/ {x++;print x,$0};END{print x}' passwd
###
常见的内置变量
awk 选项 '模式{print }'
- FS :指定每行文本的字段分隔符,缺省默认为空格或制表符(tab)。与 “-F”作用相同 -v "FS=:"
- OFS:输出时的分隔符
- NF:当前处理的行的字段个数
- NR:当前处理的行的行号(序数)
- $0:当前处理的行的整行内容
- $n:当前处理行的第n个字段(第n列)
- FILENAME:被处理的文件名
- RS:行分隔符。awk从文件上读取资料时,将根据RS的定义就把资料切割成许多条记录,而awk一次仅读入一条记录进行处理。预设值是\n
########### FS #################
[root@localhost ky15]#awk -v FS=':' '{print $1FS$3}' /etc/passwd
#此处FS 相当于于变量 -v 变量赋值 相当于 指定: 为分隔符
[root@localhost ky15]#awk -F: '{print $1":"$3}' /etc/passwd
shell中的变量
[root@localhost ky15]#fs=":";awk -v FS=$fs '{print $1FS$3}' /etc/passwd
#定义变量传给FS
######### 支持变量 ##################
[root@localhost ky15]#fs=":";awk -v FS=$fs -v OFS="+" '{print $1,$3}' /etc/passwd
#输出分隔符
-F -FS一起使用 -F 的优先级高
############ OFS ##########
[root@localhost ~]#awk -v FS=':' -v OFS='==' '{print $1,$3}' /etc/passwd
root==0
bin==1
daemon==2
adm==3
lp==4
sync==5
######## RS #######
默认是已 /n (换行符)为一条记录的分隔符
不动他
[root@localhost ~]#echo $PATH | awk -v RS=':' '{print $0}'
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/root/bin
################## NF ###################
代表字段的个数
[root@localhost ky15]#awk -F: '{print NF}' /etc/passwd
[root@localhost ky15]#awk -F: '{print $NF}' /etc/passwd
#$NF最后一个字段
[root@localhost ky15]#df|awk -F: '{print $(NF-1)}'
#倒数第二行
[root@localhost ky15]#df|awk -F "[ %]+" '{print $(NF-1)}'
################ NR ######################
行号
[root@localhost ky15]#awk '{print $1,NR}' /etc/passwd
##行号
[root@localhost ky15]#awk 'NR==2{print $1}' /etc/passwd
#只取第二行的第一个字段
[root@localhost ky15]#awk 'NR==1,NR==3{print}' passwd
#打印出1到3 行
[root@localhost ky15]#awk 'NR==1||NR==3{print}' passwd
#打印出1和3行
[root@localhost ky15]#awk '(NR%2)==0{print NR}' passwd
#打印出函数取余数为0行
[root@localhost ky15]#awk '(NR%2)==1{print NR}' passwd
#打印出函数取余数为1的行
[root@localhost ky15]#awk 'NR>=3 && NR<=6{print NR,$0}' /etc/passwd
[root@localhost ky15]#seq 10|awk 'NR>5 && NR<10'
#取 行间
6
7
8
9
[root@localhost ky15]#awk -F: '$3>1000{print}' /etc/passwd
#注意分隔符
#打印出普通用户 第三列 大于1000 的行
################ FNR ############
[root@localhost data]#cat /etc/issue |wc -l
3
[root@localhost data]#cat /etc/os-release |wc -l
16
[root@localhost data]#awk '{print FNR}' /etc/issue /etc/os-release
1
2
3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
################ FILENAME 显示处理的文件名############
[root@localhost ~]#awk -F: 'NR==2{print FILENAME}' /etc/passwd
/etc/passwd
自定义变量
[root@localhost ~]#awk -v test='hello' 'BEGIN{print test}'
hello
awk -v test1=test2="hello" 'BEGIN{test1=test2="hello";print test1,test2}'
awk -v test='hello gawk' '{print test}' /etc/fstab
awk -v test='hello gawk' 'BEGIN{print test}'
awk 'BEGIN{test="hello,gawk";print test}'
awk -F: '{sex="male";print $1,sex,age;age=18}' /etc/passwd
printf
%s:显示字符串
%d, %i:显示十进制整数
%f:显示为浮点数
%e, %E:显示科学计数法数值
%c:显示字符的ASCII码
%g, %G:以科学计数法或浮点形式显示数值
%u:无符号整数
%%:显示%自身
awk -F: '{printf "%s",$1}' /etc/passwd
awk -F: '{printf "%s\n",$1}' /etc/passwd
awk -F: '{printf "%20s\n",$1}' /etc/passwd
awk -F: '{printf "%-20s\n",$1}' /etc/passwd
awk -F: '{printf "%-20s %10d\n",$1,$3}' /etc/passwd
awk -F: '{printf "Username: %s\n",$1}' /etc/passwd
awk -F: '{printf “Username: %sUID:%d\n",$1,$3}' /etc/passwd
awk -F: '{printf "Username: %25sUID:%d\n",$1,$3}' /etc/passwd
awk -F: '{printf "Username: %-25sUID:%d\n",$1,$3}' /etc/passwd
awk -F: 'BEGIN{printf "--------------------------------\n%-20s|%10s|\n--------------------------------\n","username","uid"}{printf "%-20s|%10d|\n--------------------------------\n",$1,$3}' /etc/passwd
模式PATTERN
awk '模式{处理动作}'
PATTERN:根据pattern条件,过滤匹配的行,再做处理
模式为空
如果模式为空表示每一行都匹配成功,相当于没有额外条件
awk -F: '{print $1,$3}' /etc/passwd
正则匹配
/regular expression/:仅处理能够模式匹配到的行,需要用/ /括起来
例子:
awk '/^UUID/{print $1}' /etc/fstab
line ranges:行范围
不支持使用行号,但是可以使用变量NR 间接指定行号加上比较操作符 或者逻辑关系
算术操作符
x+y, x-y, x*y, x/y, x^y, x%y
-x:转换为负数
+x:将字符串转换为数值
比较操作符:
==, !=, >, >=, <, <=
#####逻辑
与:&&,并且关系
或:||,或者关系
非:!,取反
模式匹配符:
~ 左边是否和右边匹配,包含关系
!~ 是否不匹配
例子:
awk 'BEGIN{i=0;print i++,i}'
awk 'BEGIN{i=0;print ++i,i}
[root@centos7 ~]#awk -F: '$0 ~ /root/{print $1}' /etc/passwd
[root@centos7 ~]#awk -F: '$0 ~ "^root"{print $1}' /etc/passwd
[root@centos7 ~]#awk '$0 !~ /root/' /etc/passwd
[root@localhost ~]#awk -F: '$1 ~ /root/{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
/pat1/,/pat2/
pat代表正则,pat1到pat2 表示从正则1到正则2
例子:
[root@centos7 ~]#awk 'NR==3{print $1}' /etc/passwd
[root@centos7 ~]#seq 10 | awk 'NR>=3 && NR<=6'
[root@centos7 ~]#awk 'NR>=3 && NR<=6{print NR,$0}' /etc/passwd
[root@centos7 ~]#awk '/^bin/,/^adm/' /etc/passwd
#bin开头 到adm开头
[root@localhost ky15]#awk '{print $1,NR}' /etc/passwd
##行号
[root@localhost ky15]#awk 'NR==2{print $1}' /etc/passwd
#只取第二行的第一个字段
[root@localhost ky15]#awk 'NR==1,NR==3{print}' passwd
#打印出1到3 行
[root@localhost ky15]#awk 'NR==1||NR==3{print}' passwd
#打印出1和3行
[root@localhost ky15]#awk '(NR%2)==0{print NR}' passwd
#打印出函数取余数为0行
[root@localhost ky15]#awk '(NR%2)==1{print NR}' passwd
#打印出函数取余数为1的行
[root@localhost ky15]#awk 'NR>=3 && NR<=6{print NR,$0}' /etc/passwd
[root@localhost ky15]#seq 10|awk 'NR>5 && NR<10'
#取 行间
6
7
8
9
[root@localhost ky15]#awk '$3>1000{print}' /etc/passwd
#注意分隔符
#打印出普通用户 第三列 大于1000 的行
awk ‘ 模式 { }’
BEGIN END
BEGIN{}:仅在开始处理文件中的文本之前执行一次
END{}:仅在文本处理完成之后执行一次
例子:
[root@localhost ~]#awk -F: 'BEGIN {print "hello"} {print $1}' /etc/passwd |head -n3
#先处理BEGIN 中的式子
hello
root
bin
[root@localhost ~]#awk -F: 'END {print "hello"} {print $1}' /etc/passwd |head -n3
#先处理BEGIN 中的式子
root
bin
hello
awk -F: 'BEGIN{printf "--------------------------------\n%-20s|%10s|\n--------------------------------\n","username","uid"}{printf "%-20s|%10d|\n--------------------------------\n",$1,$3}' /etc/passwd
关系表达式(扩展)
关系表达式结果为“真”才会被处理
真:结果为非0值,非空字符串
假:结果为空字符串或0值
[root@localhost ~]#seq 10 |awk 1
1
2
3
4
5
6
7
8
9
10
[root@localhost ~]#seq 10 |awk 0
seq 10 |awk 'n++' 打印除了第一行
seq 10 |awk '!n++' 只打第一行
seq 10 |awk '!0'
seq 10 |awk 'i=!i' 奇数行
seq 10 |awk -v i=1 'i=!i' 偶数行
seq 10 |awk '!(i=!i)' 偶数行
条件判断 (扩展)
awk 选项 '模式 {actions}'
条件判断写在 actions里
if(condition){statement;…}[else statement]
if(condition1){statement1}else if(condition2){statement2}else if(condition3){statement3}...... else {statementN}
condition1:条件
statement1:语句
if语句:awk的if语句也分为单分支、双分支和多分支
单分支为if(判断条件){执行语句}
双分支为if(判断条件){执行语句}else{执行语句}
多分支为if(判断条件){执行语句}else if(判断条件){执行语句}else if(判断条件){执行语句}else if(判断条件){执行语句
#写在动作里
[root@localhost ~]#awk -F: '{if($3>1000)print $1,$3}' /etc/passwd
nfsnobody 65534
mysql 1001
lisi 1002
liwu 1003
[root@localhost ~]#awk -F: '{if($3>1000){print $1,$3}else{print $3}}' /etc/passwd
for | while
for(expr1;expr2;expr3) {statement;…}
for(variable assignment;condition;iteration process) {for-body}
for(var in array) {for-body}
awk 'BEGIN{sum=0;for(i=1;i<=100;i++){sum+=i};print sum}'
5050
for((i=1,sum=0;i<=100;i++));do let sum=i+sum;done;echo $sum
5050
计算
[root@localhost ky15]#awk 'BEGIN{i=0;print i++,i}'
0 1
[root@localhost ky15]#awk 'BEGIN{i=0;print ++i,i}'
1 1
awk的运算:
[root@localhost ~]# awk 'BEGIN{x=10;print x}' //如果不用引号awk就当作一个变量来输出了,所以不需要加$了
10
[root@localhost ~]# awk 'BEGIN{x=10;print x+1}' //BEGIN在处理文件之前,所以后面不跟文件名也不影响
11
[root@localhost ~]# awk 'BEGIN{x=10;x++;print x}'
11
[root@localhost ~]# awk 'BEGIN{print x+1}' //不指定初始值,初始值就为0,如果是字符串,则默认为空
1
[root@localhost ~]# awk 'BEGIN{print 2.5+3.5}' //小数也可以运算
6
[root@localhost ~]# awk 'BEGIN{print 2-1}'
1
[root@localhost ~]# awk 'BEGIN{print 3*4}'
12
[root@localhost ~]# awk 'BEGIN{print 3**2}'
9
[root@localhost ~]# awk 'BEGIN{print 2^3}' //^和**都是幂运算
8
[root@localhost ~]# awk 'BEGIN{print 1/2}'
0.5
数组 (awk 数组来计算 )
awk数组特性:
-
awk的数组是关联数组(即key/value方式的hash数据结构),索引下标可为数值(甚至是负数、小数等),也可为字符串 1. 在内部,awk数组的索引全都是字符串,即使是数值索引在使用时内部也会转换成字符串 2. awk的数组元素的顺序和元素插入时的顺序很可能是不相同的
-
awk数组支持数组的数组
访问、赋值数组元素
arr[idx]
arr[idx] = value
索引可以是整数、负数、0、小数、字符串。如果是数值索引,会按照CONVFMT变量指定的格式先转换成字符串
例子:
[root@centos ~]#awk 'BEGIN{a[1]="zhangsan";print a[1]}'
zhangsan
[root@centos ~]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"]}'
数组长度
awk提供了 length() 函数来获取数组的元素个数,它也可以用于获取字符串的字符数量。还可以获取数值转换成字符串后的字符数量。
例子:
awk 'BEGIN{arr[1]=1;arr[2]=2;print length(arr);print length("hello")}'
[root@VM-4-16-centos ~]#awk 'BEGIN{a[1]="zhangsan";print a[1];print length(a)}'
# length(a) length(数组名) 可以查看数组长度
zhangsan
1
遍历数组
格式:
for(var in array) {for-body}
例子:
awk 'BEGIN{students[1]="zhaizong";students[2]="hezong";students[3]="haizong";for(x in students){print x":"students[x]}}'
将下标转换成 字母
a
aa 后就会不确定
实际案例
去除重复行
cat test.txt
abc
def
ghi
abc
ghi
xyz
mnopq
abc
awk '{a[$0]++}END{for (i in a){print i,a[i]}}' test.txt
awk '!a[$0]++' test.txt
格式:
awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"]}'
awk '!line[$0]++' dupfile
awk '{print !line[$0]++, $0, line[$0]}' dupfile
awk '{!line[$0]++;print $0, line[$0]}' dupfile
遍历数组
for(var in array) {for-body}
awk 'BEGIN{students[1]="zhaizong";students[2]="hezong";students[3]="haizong";for(x in students){print x":"students[x]}}'
ss -nta|awk 'NR!=1{print $1}'|sort
ss -nta|awk 'NR!=1{state[$2]++}'
ss -nta|awk 'NR!=1{state[$1]++}END{for(i in state){print i,state[i]}}'
awk 脚本
将awk程序写成脚本,直接调用或执行
[root@centos7 ~]#vim passwd.awk
{if($3>=1000)print $1,$3}
[root@localhost data]#awk -F: -f passwd.awk /etc/passwd
nfsnobody 65534
zhangsan 1000
mysql 1001
[root@centos7 ~]#cat test.awk
#!/bin/awk -f 声明解释器
#this is a awk script
{if($3>=1000)print $1,$3}
[root@centos8 ~]#chmod +x test.awk
[root@centos8 ~]#./test.awk -F: /etc/passwd
nobody 65534
wang 1000