目录
正则表达式
1:什么是正则表达式
正则表达式由普通字符和元字符组成的表达式, 通过此模式,用来匹配特定的内容。
普通字符包括大小写的字母和数字。
元字符,是一些特殊符号,这些字符并不表示字面上的含义, 而会被解释为一些特定的含义.
正则表达式区分大小写。
正则表达式主要用于简化管理员的工作负担。
2: 元字符的完整列表:
https://www.runoob.com/regexp/regexp-metachar.html
2.1或:
字符 | 描述 | 举例 |
---|---|---|
x|y | 匹配 x 或 y。 | ‘z|food’ 能匹配 “z” 或 “food”。’(z|f)ood’ 则匹配 “zood” 或 “food”。 |
2.2匹配字符:
字符 | 描述 | 举例 |
---|---|---|
. | 匹配任意单个字符 | |
[] | 匹配指定范围内的任意单个字符 | [a-z]匹配 ‘a’ 到 ‘z’ 范围内的任意小写字母字符 |
[^] | 匹配指定范围以外的任意单个字符(出现在[ ]中的^代表排除) | [^0-9] 排除纯数字 [^a-z] 排除纯字母 |
2.3匹配次数:
字符 | 描述 | 举例 |
---|---|---|
* | 匹配前面的子表达式零次或多次。 | 例如,zo* 能匹配 “z” 以及 “zoo”。* 等价于{0,}。 |
+ | 匹配前面的子表达式一次或多次 | 例如,‘zo+’ 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。+ 等价于 {1,}。 |
? | 匹配前面的子表达式零次或一次。 | 例如,“do(es)?” 可以匹配 “do” 或 “does” 。? 等价于 {0,1}。 |
{n} | n 是一个非负整数。匹配确定的 n 次。 | 例如,‘o{2}’ 不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的两个 o。 |
{n,} | n 是一个非负整数。至少匹配n 次。 | 例如,‘o{2,}’ 不能匹配 “Bob” 中的 ‘o’,但能匹配 “foooood” 中的所有 o |
{n,m} | m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。 | 例如,“o{1,3}” 将匹配 “fooooood” 中的前三个 o |
2.4匹配位置:
锚指定正则表达式所要匹配的文本在文本行中所处的位置。
字符 | 描述 | 举例 |
---|---|---|
^ | 匹配字符串的开始位置 | ^huazai开头的 |
$ | 匹配输入字符串的结束位置 | 007$结尾的 |
^$ | 匹配空行 |
2.5分组:
正则表达式可以通过" () "来进行分组
所谓的分组就是使用小括号将一些项包括起来,使其成为独立的逻辑域,那么就可以像处理一个独立单元一样去处理小括号的内容。
在实际应用中,往往需要重复多个字符,例如我想重复ab两个字符,使用以下代码就不合适了,代码如下:
ab{3}
以上正则表达式只能够重复3次b。
为了实现重复多个字符可以使用小括号来指定子表达式或者说分组来实现此功能,例如:
(ab){3}
上面的正则就可以重复ab了。
2.6其他:
字符 | 描述 | 举例 |
---|---|---|
\b | 匹配一个单词边界,也就是指单词和空格间的位置 | 例如, ‘er\b’ 可以匹配"never" 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。 |
\B | 匹配非单词边界 | ‘er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。 |
\d | 匹配一个数字字符。等价于 [0-9] | |
\D | 匹配一个非数字字符。等价于 [^0-9] | |
\n | 匹配一个换行符。 | |
\r | 匹配一个回车符 | |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 | |
\S | 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 | |
\w | 匹配字母、数字、下划线。等价于’[A-Za-z0-9_]’。 | |
\W | 匹配非字母、数字、下划线。等价于 ‘[^A-Za-z0-9_]’。 |
一:cut(切割)
cut命令用来显示行中的指定部分,删除文件中指定字段.
语法:
cut(选项) 文件
选项:
-c:仅显示行中指定范围的字符;
-d:指定字段的分隔符,默认的字段分隔符为“TAB”;
-f:显示指定字段的内容;
--help:显示指令的帮助信息;
--version:显示指令的版本信息。
实例:
例如有一个学生报表信息,包含No、Name、Mark、Percent:
[root@localhost text]# cat test.txt
No Name Mark Percent
01 tom 69 91
02 jack 71 87
03 alex 68 98
使用 -f 选项提取指定字段:
截取第一个字段
[root@localhost text]# cut -f 1 test.txt
No
01
02
03
截取第二,三字段
[root@localhost text]# cut -f2,3 test.txt
Name Mark
tom 69
jack 71
alex 68
使用 -d 选项指定字段分隔符:
[root@localhost text]# cat test2.txt
No;Name;Mark;Percent
01;tom;69;91
02;jack;71;87
03;alex;68;98
截取第二个字段
[root@localhost text]# cut -f2 -d";" test2.txt
Name
tom
jack
alex
cut命令可以将一串字符作为列来显示,字符字段的记法:
- N-:从第N个字节、字符、字段到结尾;
- N-M:从第N个字节、字符、字段到第M个(包括M在内)字节、字符、字段;
- -M:从第1个字节、字符、字段到第M个(包括M在内)字节、字符、字段。
[root@localhost text]# cat test.txt
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
-c 表示字符;
打印第1个到第3个字符:
[root@localhost text]# cut -c1-3 test.txt
abc
abc
abc
abc
abc
打印前2个字符:
[root@localhost text]# cut -c-2 test.txt
ab
ab
ab
ab
ab
打印从第5个字符开始到结尾:
[root@localhost text]# cut -c5- test.txt
efghijklmnopqrstuvwxyz
efghijklmnopqrstuvwxyz
efghijklmnopqrstuvwxyz
efghijklmnopqrstuvwxyz
efghijklmnopqrstuvwxyz
二:sort(排序)
sort命令可以将文件进行排序,并将排序结果标准输出。
语法:
sort(选项) 文件
选项:
-n:依照数值的大小排序;
-o<输出文件>:将排序后的结果存入制定的文件;
-u:重复行仅显示一次
-k: 按照第几个域排序
-r:以相反的顺序来排序;
-t<分隔字符>:指定排序时所用的栏位分隔字符;
举例:
原始文件里有两行eee
[root@mail text]# cat sort.txt
aaa:10:1.1
ccc:30:3.3
ddd:40:4.4
bbb:20:2.2
eee:50:5.5
eee:50:5.5
忽略相同行使用:-u选项
[root@mail text]# sort -u sort.txt
aaa:10:1.1
bbb:20:2.2
ccc:30:3.3
ddd:40:4.4
eee:50:5.5
sort的-n、-r、-k、-t选项的使用:
原始文件:
[root@mail text]# cat sort.txt
AAA:BB:CC
aaa:30:1.6
ccc:50:3.3
ddd:20:4.2
bbb:10:2.5
eee:40:5.4
eee:60:5.1
将BB列按照数字从小到大顺序排列:
[root@mail text]# sort -nk 2 -t: sort.txt
AAA:BB:CC
bbb:10:2.5
ddd:20:4.2
aaa:30:1.6
eee:40:5.4
ccc:50:3.3
eee:60:5.1
将CC列数字从大到小顺序排列:
[root@mail text]# sort -nrk 3 -t: sort.txt
eee:40:5.4
eee:60:5.1
ddd:20:4.2
ccc:50:3.3
bbb:10:2.5
aaa:30:1.6
AAA:BB:CC
三:uniq(去重)
uniq命令可以去除排序过的文件中的重复行,因此uniq经常和sort合用。
也就是说,为了使uniq起作用,所有的重复行必须是相邻的。
选项:
-d:仅显示重复行
-u:仅显示非重复行
-c:显示行连续重复的次数
举例:
列出以前用户登录的信息的,以空格分隔的第1列,并且只显示不重复行
[root@localhost ~]# last |cut -d" " -f1|uniq -u
reboot
reboot
reboot
reboot
wtmp
列出以前用户登录的信息的,以空格分隔的第1列,并且只显示有重复数据行,每种重复行只显示一行
[root@localhost ~]# last |cut -d" " -f1|uniq -d
root
root
root
root
列出以前用户登录的信息的,以空格分隔的第1列,并且打印每一重复行出现次数
[root@localhost ~]# last |cut -d" " -f1|uniq -c
8 root
1 reboot
2 root
1 reboot
2 root
1 reboot
3 root
1 reboot
1
1 wtmp
四:wc(计数)
选项:
-l : 多少行
-m : 多少字符
-w : 多少字(空格,制表符,换行符隔开的)
举例:
查看/etc/passwd里有多少行
[root@localhost ~]# cat /etc/passwd|wc -l
22
[root@localhost ~]# cat /tmp/t1.txt
huazai 007
查看有多少个字
[root@localhost ~]# cat /tmp/t1.txt |wc -w
2
查看有多少个字符
[root@localhost ~]# cat /tmp/t1.txt |wc -m
11
五:find(在指定目录下查找文件)
find命令用来在指定目录下查找文件。
find命令选项基本格式
find 目录 -选项 动作[-print -exec -ok ...]
常用选项:
-a:and 必须满足两个条件才显示
-o:or 只要满足一个条件就显示
-name:按照文件名查找文件
-iname:按照文件名查找文件(忽略大小写)
-type:根据文件类型进行搜索
-perm:按照文件权限来查找文件
-user 按照文件属主来查找文件。
-group 按照文件所属的组来查找文件。
-fprint 文件名:将匹配的文件输出到文件。
-newer file1 ! newer file2 查找更改时间比文件file1新但比文件file2旧的文件
常用动作:
-print:默认动作,将匹配的文件输出到标准输出
-exec:对匹配的文件执行该参数所给出的命令。相应命令的形式为'command' { } \;,注意{ }和\;之间的空格。
-ok:和-exec的作用相同,只不过以一种更为安全的模式来执行该参数所给出的命令,在执行每一个命令之前,都会给出提示,让用户来确定是否执行。
-delete :将匹配到的文件删除
5.1:根据文件名进行匹配
列出当前目录及子目录下所有文件和文件夹
find .
在/home目录下查找以.txt结尾的文件名
find /home -name "*.txt"
同上,但忽略大小写
find /home -iname "*.txt"
当前目录及子目录下查找所有以.txt或.pdf结尾的文件
[root@localhost home]# find /home/ -name "*.txt" -o -name "*.pdf"
/home/a.txt
/home/a.pdf
当前目录及子目录下查找所有以a开头和以.txt结尾的文件
[root@localhost home]# find /home/ -name "*.txt" -a -name "a*"
/home/a.txt
搜索/home目录下txt结尾的文件,并将输出到指定文件中(re.txt)
[root@localhost home]# find /home/ -type f -name "*.txt" -fprint /tmp/re.txt
[root@localhost home]# cat /tmp/re.txt
/home/a.txt
/home/b.txt
5.2:根据文件类型进行搜索
find . -type 类型参数
类型参数列表:
f 普通文件
l 符号连接(软连接)
d 目录
b 块设备
s 套接字
[root@localhost home]# find /home/ -type f
/home/a.txt
/home/a.pdf
[root@localhost home]# find /usr/bin/ -type l
[root@localhost home]# find /usr/local/ -type d
[root@localhost home]# find /dev/ -type b
/dev/dm-1
/dev/dm-0
/dev/sr0
/dev/sda2
/dev/sda1
/dev/sda
[root@localhost home]# find /var/lib/ -type s
/var/lib/mysql/mysql.sock
5.3:基于目录深度搜索
向下最大深度限制为3
find /usr/local/ -maxdepth 3 -type d
搜索出深度距离当前目录至少2个子目录的所有文件
find /usr/local/ -mindepth 2 -type f
5.4:根据文件时间戳进行搜索
UNIX/Linux文件系统每个文件都有三种时间戳:
- 访问时间(-atime/天,-amin/分钟):用户最近一次访问时间。
- 修改时间(-mtime/天,-mmin/分钟):文件最后一次修改时间
- 变化时间(-ctime/天,-cmin/分钟):文件数据元(例如权限等)最后一次修改时间。
stat 命令查看:
[root@localhost amoeba-mysql]# stat /etc/passwd
文件:"/etc/passwd"
大小:1015 块:8 IO 块:4096 普通文件
设备:fd00h/64768d Inode:17135967 硬链接:1
权限:(0644/-rw-r--r--) Uid:( 0/ root) Gid:( 0/ root)
环境:system_u:object_r:passwd_file_t:s0
最近访问:2020-02-11 05:50:51.523891795 +0800
最近更改:2020-02-11 05:50:51.514141787 +0800
最近改动:2020-02-11 05:50:51.515225121 +0800
创建时间:-
搜索最近七天内被访问过的所有文件
find /etc/ -type f -atime -7
搜索超过七天内(7天外)被访问过的所有文件
find /etc -type f -atime +7
5.5:根据文件大小进行匹配
find . -type f -size 文件大小单元
文件大小单元:
b —— 块(512字节)
c —— 字节
w —— 字(2字节)
k —— 千字节
M —— 兆字节
G —— 吉字节
搜索大于10KB的文件
find /etc/ -type f -size +10k
搜索小于10KB的文件
find /etc/ -type f -size -10k
搜索等于10KB的文件
find /etc/ -type f -size 10k
搜索大于10G的日志文件,并删除
find /var/log -type f -name "*.log" -size +10G -delete
5.6:根据文件权限/所有权进行匹配
指定目录下搜索出权限为777的文件
find / -type f -perm 777
找出指定目录下权限不是644的txt文件
find / -type f -name "*.txt" ! -perm 644
找出/home目录用户huazai拥有的所有文件
#useradd huazai
[root@localhost home]# find /home/ -type f -user huazai
/home/huazai/.bash_logout
/home/huazai/.bash_profile
/home/huazai/.bashrc
找出/home目录用户组huazai拥有的所有文件
[root@localhost home]# find /home/ -type f -group huazai
/home/huazai/.bash_logout
/home/huazai/.bash_profile
/home/huazai/.bashrc
5.7:借助-exec选项与其他命令结合使用
找出/tmp目录下所有root的文件,并把所有权更改为用户huazai
find /tmp/ -type f -user root -exec chown huazai {} \;
上例中,{} 用于与-exec选项结合使用来匹配所有文件,然后会被替换为相应的文件名。
找出自己家目录下所有的.sh文件并删除
[root@localhost home]# find $HOME -name "*.sh" -ok rm {} \;
< rm ... /root/install_lnmp.sh > ? y
-ok和-exec行为一样,不过它会给出提示,是否执行相应的操作。
查找/home目录下所有.txt文件并把他们拼接起来写入到all.txt文件中
find /home/ -type f -name "*.txt" -exec cat {} \;>all.txt
查找/home目录下所有.txt文件并把他们复制到/opt/backup文件中
find /home/ -type f -name "*.txt" -exec cp {} /opt/backup/ \;
在/var/log目录中查找更改时间在5日以前的文件并删除它们:
find /var/log -type f -mtime +5 -exec rm {} \;
六:grep(全局搜索并打印)
grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。
grep 是linux 中最常用的“文本处理工具之一” 与sed awk 合称为linux中的三剑客!
grep 就像你在windows中打开txt文件,使用快捷键“Ctrl+F” 在文本中查找某个字符串一样,可以把grep 理解为字符查找工具
grep语法:
grep [option] pattern file
grep 选项 模式 文件
常用选项:
-i:忽略大小写
-v:反向查找,显示没有匹配模式的行
-c: 仅显示匹配行数,不显示匹配内容
-n: 显示行号
-o:只显示被模式匹配的字符串
-r:递归,读取目录下所有文件进行匹配
-l: 不显示输出的匹配结果,仅显示匹配的文件名
打印匹配行的:
前n行
或后n行
或前后n行
-B, --before-context=NUM print NUM lines of leading context
-A, --after-context=NUM print NUM lines of trailing context
-C, --context=NUM print NUM lines of output context
grep 利用正则匹配ip地址和端口号
grep -Eo "[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}:[0-9]{1,5}" /tmp/t.json
10.10.116.10:30866
10.10.116.11:8080
10.96.0.207:48069
10.99.110.41:30815
10.99.110.41:30817
在/etc目录下,把包含huazai 字符的文件名显示出来
[root@localhost home]# grep huazai /etc/ -rl
/etc/group
/etc/gshadow
/etc/passwd
/etc/shadow
/etc/subgid
/etc/subuid
[root@localhost home]# grep huazai /etc/passwd -o
huazai
huazai
-i:在搜索的时候忽略大小写
[root@localhost ~]# cat /etc/passwd|grep -i "SSH"
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
-n: 显示结果所在行号
[root@localhost ~]# cat /etc/passwd|grep -ni "SSH"
17:sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
-c:统计匹配到的行数
[root@localhost ~]# cat /etc/passwd|grep "root"
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost ~]# cat /etc/passwd|grep -c "root"
2
-w:精确匹配某个单词
[root@localhost ~]# cat /etc/passwd.bak|grep -w "root"
root:x:0:0:root:/root:/bin/bash
rootroo:x:0:0:root:/root:/bin/bash #不会显示rootroo的
-e:实现多个选项的匹配。逻辑或or的关系
==egrep
==grep -E
[root@localhost ~]# cat /etc/passwd.bak|egrep -w "root|sshd"
root:x:0:0:root:/root:/bin/bash
rootroo:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
-q: 静默模式,不输出任何信息 判断:echo $?
[root@localhost ~]# cat /etc/passwd.bak|grep -q "root"
v:输出不带关键字的行(反向查询,反向匹配)
[root@localhost ~]# cat /etc/passwd.bak|grep -v "root"
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
七:sed(流编辑器)
sed是一种流编辑器,它是文本处理中常用的工具,能够完美的配合正则表达式使用,功能不同凡响。
处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。
接着处理下一行,这样不断重复,直到文件末尾。
文件内容并没有 改变,除非你使用(-i)选项。
Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作。
7.1 命令格式:
sed [选项] ‘地址定界 动作’ file_name
7.2 常用选项:
-e:承接多个筛选条件
-n或--quiet或——silent:只显示匹配处理的行(否则会输出所有)(也就是关闭默认的输出)
-i:直接修改文本内容
-p打印
深入理解-n和-p选项的用法:
[root@centos6 ~]# cat a.txt
asdf;1324;fdsag
1234567890
qwer
asdasdsadasdasdas
首先sed是有一个默认输出的,也就是将所有文件内容都输出,加上命令行中的替换,那么输出结果就是下面这样
sed 's/1324/aaaa/' a.txt > b.txt
[root@centos6 ~]# cat b.txt
asdf;aaaa;fdsag
1234567890
qwer
asdasdsadasdasdas
这行的意思就是:首先sed默认输出文件全部内容,然后p又将匹配到的内容打印了一遍,也就是会输出两遍匹配到的内容
[root@centos6 ~]# sed 's/1324/aaaa/p' a.txt > b.txt
[root@centos6 ~]# cat b.txt
asdf;aaaa;fdsag
asdf;aaaa;fdsag
1234567890
qwer
asdasdsadasdasdas
这行就是sed -n屏蔽默认输出然后s替换,p再将匹配到的内容打印出来,所以只显示了一行,也就是匹配到的那一行
[root@centos6 ~]# sed -n 's/1324/aaaa/p' a.txt > b.txt
[root@centos6 ~]# cat b.txt
asdf;aaaa;fdsag
这行就是sed -n选项屏蔽默认输出,s替换,但是没有p就不会将匹配到的内容输出
[root@centos6 ~]# sed -n 's/1324/aaaa/' a.txt > b.txt
[root@centos6 ~]# cat b.txt
[root@centos6 ~]#
-e的用法:
将num.txt中的11替换成22, 55替换成99.
sed -e 's/11/22/' -e 's/55/99/' num.txt
7.3 定址:
可以通过定址来定位你所希望编辑的行,该地址用数字构成,用逗号分隔的两个行数表示以这两行为起止的行的范围(包括行数表示的那两行)。如1,3表示1,2,3行,美元符号($)表示最后一行。也可通过模式来确定,或行号和模式的结合
例子:
x x为行号,如1
x,y 表范围,如2,5表示2到5行
/pattern/ 匹配到此模式的行
/pattern/,/pattern/ 包含两个模式的行
x,/pattern/ 通过行号或模式定位
$ 最后一行
示例:
7.3.1 空地址:
即对全文就行处理 g是全局替换(s)
[root@master ~]# sed 's/root/ROOT/g' /etc/passwd
从第三次开始替换
[root@master ~]# echo "sksksksksksk" | sed 's/sk/SK/3g'
skskSKSKSKSK
所有已mysql开头的都被替换为mysql_wg007 (&符号表示被匹配字符)
[root@master ~]# sed 's/^mysql/&_wg007/' /tmp/passwd
删除空行(d)
sed '/^$/d' /tmp/passwd
7.3.2 单地址:
打印第二行的内容
[root@master ~]# sed -n '2p' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
删除第一行的内容
[root@master ~]# sed '1d' /tmp/passwd
7.3.3 地址范围:
显示1-3行的内容
[root@master ~]# sed -n '1,3p' /tmp/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
显示:从第三行开始,往下再来3行
[root@master ~]# sed -n '3,+3p' /tmp/passwd
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
删除1-3行的内容
[root@master ~]# sed '1,3d' /tmp/passwd
7.3.4步进地址表示法:
打印奇数行
[root@master ~]# sed -n '1~2p' /tmp/passwd
打印偶数行
[root@master ~]# sed -n '2~2p' /tmp/passwd
7.4 常用动作:
常用动作/命令:
s : 替换
a :新增行, a 的后面可以是字串,而这些字串会在新的一行出现(匹配行的下一行)
c :替换行,将匹配的行替换为指定字符“test”
d :删除行,因为是删除,所以 d 后面通常不接任何参数,直接删除地址表示的行;
i :插入行, i 的后面可以接字串,而这些字串会在新的一行出现(匹配行的上一行);
p :打印,即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行
s :替换,可以直接进行替换的工作,通常这个 s 的动作可以搭配正规表示法,例如 1,20s/old/new/g 一般是替换符合条件的字符串而不是整行
w :将模式空间匹配到的行,写入指定文件中
r :将PATH中指定的文件写入匹配到的行下方,多用于文件合并。
=:显示行号
! : 条件取反,一般用于模式之后,命令之前
示例:
7.4.1: (a:追加)
在以#号开头的行号后面新增一行字符“123”
[root@master ~]# sed '/^#/a "123"' /tmp/passwd
#root:x:0:0:root:/root:/bin/bash
"123"
在第一行后面新增字符“huazai007”
[root@master ~]# sed '1a"huazai007"' /tmp/passwd
#root:x:0:0:root:/root:/bin/bash
"huazai007"
7.4.2: ( i:插入)
在第三行的前面插入字符“huazai007”
[root@master ~]# sed '3i"huazai007"' /tmp/passwd
#root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
"huazai007"
daemon:x:2:2:daemon:/sbin:/sbin/nologin
在以lp开头的行前插入一行
[root@master ~]# sed '/^lp/i"huazai007"' /tmp/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
"huazai007"
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
在以nologin结尾的行前插入一行
smmsp:x:51:51::/var/spool/mqueue:/sbin/nologin
"huazai007"
mysql:x:27:27:MariaDB Server:/var/lib/mysql:/sbin/nologin
[root@master ~]# sed '/nologin$/i"huazai007"' /tmp/passwd
7.4.3: ( c:整行替换)
当前行只要包含“”root“” 这个字符串,整行会被替换为“huazai007”
[root@master ~]# sed '/root/c"huazai007"' /tmp/passwd
"huazai007"
将以#号开头的替换为huazai007
[root@master ~]# sed '/^#/c"huazai007"' /tmp/passwd
"huazai007"
7.4.4: ( w : 将模式空间匹配到的行,写入指定文件中)
将以#号开头的行写入到result.txt文件
[root@master ~]# sed '/^#/w result.txt' /tmp/passwd
[root@master ~]# cat result.txt
#root:x:0:0:root:/root:/bin/bash
将1-3行写入到result文件
[root@master ~]# sed '1,3w result.txt' /tmp/passwd
7.4.5:(r /PATH : 将PATH中指定的文件写入匹配到的行下方)
多用于文件合并
将result.txt 的内容写入到 以mysql开头并且以nologin结尾的行后面
[root@master ~]# sed '/^mysql.*nologin$/r result.txt' /tmp/passwd
7.4.6: (=:显示行号)
显示最后一行的行号
24
mysql:x:27:27:MariaDB Server:/var/lib/mysql:/sbin/nologin
[root@master ~]# sed '$=' /tmp/passwd
显示以ftp开头的行号,在匹配行上方显示行号
[root@master ~]# sed '/^ftp.*nologin$/=' /tmp/passwd
12
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
7.4.7: ( ! : 条件取反)
除了#号开头的都打印出来
sed -n '/^#/!p' /tmp/passwd
八:awk(文本处理工具)
awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。
简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理
8.1awk工作流程:
awk工作流程是这样的:读入有’\n’换行符分割的一条记录,然后将记录按指定的域分隔符划分域,$0则表示所有域, 1 表 示 第 一 个 域 , 1表示第一个域, 1表示第一个域,n表示第n个域。
8.2语法格式:
awk [ -F 分隔符 ] ' /模式/{操作} ' 文件名
所以说awk脚本是由模式和操作组成的。
8.2.1 模式:
模式可以是以下任意一个:
- /正则表达式/:使用通配符的扩展集。
- 关系表达式:使用运算符进行操作,可以是字符串或数字的比较测试。
- 模式匹配表达式:用运算符(匹配)和!(不匹配)。
- BEGIN语句块、pattern语句块、END语句块
8.2.2 操作:
操作由一个或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大括号内,主要部分是:
- 变量或数组赋值
- 输出命令
- 内置函数
- 控制流语句
常见的操作为:
print
printf
例子:(print)
cat /etc/passwd |awk -F ':' '{print $1}'
例子:(printf)
%s %c %d %f都是格式替代符
%s:字符串
%c:字符
%d:整数
%f:浮点数
%-10s 指一个宽度为10个字符(-表示左对齐,没有则表示右对齐),任何字符都会被显示在10个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。
%-4.2f 指格式化为小数,其中.2指保留2位小数
awk -F: '{printf "%5d\n",$3}' /etc/passwd
[root@localhost ~]# echo "0.123456"|awk '{printf "%.2f\n",$0 }'
0.12
8.3 常用选项:
-F 指定域分隔符(默认为空格或tab键)
-f 指定从脚本文件中读取awk命令
-v var=value 赋值一个用户定义变量,将外部变量传递给awk
8.4 常用内置变量
$n 当前记录的第n个字段,比如n为1表示第一个字段,n为2表示第二个字段。
$0 这个变量包含执行过程中当前行的文本内容。
FS 设置输入域分隔符,等价于命令行 -F选项
NF 浏览记录的域的个数
NR 已读的记录数
OFS 输出域分隔符
ORS 输出记录分隔符
打印每一行的第二和第三个字段:
awk -F ":" '{ print $2,$3 }' /etc/passwd
输出第二行(NR)
[root@localhost ~]# awk -F ":" 'NR==2 {print}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
输出第三行以后的行
[root@localhost ~]# awk -F ':' 'NR>3 {print}' /etc/passwd
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
使用print $NF可以打印出一行中的最后一个字段,使用$(NF-1)则是打印倒数第二个字段,其他以此类推:
echo -e "line1 f2 f3n line2 f4 f5" | awk '{print $NF}'
f3
f5
echo -e "line1 f2 f3n line2 f4 f5" | awk '{print $(NF-1)}'
f2
f4
8.5 BEGIN和END:
格式如下:
awk 'BEGIN{ commands } pattern{ commands } END{ commands }'
执行过程如下:
第一步:执行BEGIN{ commands }语句块中的语句;
第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ commands }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
第三步:当读至输入流末尾时,执行END{ commands }语句块。
BEGIN和END部分在awk中都仅执行一次。
BEGIN在程序一开始时, 改变awk分隔数据行的方式、设定变量的起始值、印出一行title。此时不需要读入任何数据行。
而END用来打印结尾信息或者用来输出统计信息等。
实例1:
打印最后一个字段
awk 'BEGIN{ FS=":" } { print $NF }' /etc/passwd
echo -e "A line 1nA line 2" | awk 'BEGIN{ print "Start" } { print } END{ print "End" }'
Start
A line 1
A line 2
End
实例2:
累计销售文件xs中的销售金额(假设销售金额在记录的第三字段):
cat sx
一:50件:200.00
二:60件:300.00
三:70件:400.00
[root@localhost ~]# awk 'BEGIN {FS=":";print "统计销售金额";total=0} {print $3;total=total+$3;} END {printf "销售金额总计: %.2f\n",total}' sx
统计销售金额
200.00
300.00
400.00
销售金额总计: 900.00
8.5 awk流程控制语句
8.5.1 awk中的流程控制语句-if条件语句
格式:
if(表达式)
语句1
else
语句2
格式中语句1可以是多个语句,为了方便判断和阅读,最好将多个语句用{}括起来。
awk分枝结构允许嵌套,其格式为:
if(表达式)
{语句1}
else if(表达式)
{语句2}
else
{语句3}
实例:
awk 'BEGIN{
test=100;
if(test>90){
print "very good";
}
else if(test>60){
print "good";
}
else{
print "no pass";
}
}'
每条命令语句后面可以用;分号结尾。
假如$1==root 打印第一个字段,否则打印第二个字段
awk -F : '{if ($1=="root") print $1;else print $2}' /etc/passwd
显示用户信息配置文件中用户id大于等于500的(普通用户)用户数量
方法1:
awk -F: 'BEGIN {sum=0} {if ($3>=500) sum++} END {print sum}' /etc/passwd
方法2:
-v:设置一个变量
awk -F: -v sum=0 '{if ($3>=500) sum++}END{print sum}' /etc/passwd
8.5.2 awk中的流程控制语句-while循环语句
格式1:
while(表达式)
{语句}
实例:
1+2+…100
awk 'BEGIN {test=100;total=0;while(i<=test){total+=i;i++} {print total}}'
5050
显示用户信息配置文件中$1到$3的字段
awk -F: '{i=1;while (i<=3) {print $i;i++}}' /etc/passwd
8.5.3 awk中的流程控制语句-for循环语句
格式:
for(变量;条件;表达式)
{语句}
实例:
显示用户信息配置文件中$1到$3字段
awk -F: '{for(i=1;i<=3;i++) print $i}' /etc/passwd
awk 'BEGIN{total=0;for(i=0;i<=100;i++){total+=i} {print total}}'
5050