1、特殊符号
1.1 引号系列
双引号(’ ‘)、单引号(” “)、反引号(“)、不加引号
单引号:所见即所得,单引号里面的内容会原封不动地输出
双引号:和单引号类似,对双引号里面的特殊符号会进行解析,对于{}(通配符)不解析
不加引号:和双引号类似,额外支持通配符(匹配文件),如:*.log{1..10}
反引号:优先执行,先执行反引号里面的命令
单引号:
[root@linux-87-01 ~]# echo 'hello'
hello
[root@linux-87-01 ~]# echo '`hostname`'
`hostname`
[root@linux-87-01 ~]# echo '$UID'
$UID
[root@linux-87-01 ~]#
双引号:
[root@linux-87-01 ~]# echo "{1..5}"
{1..5}
[root@linux-87-01 ~]# echo "$(whoami)"
root
[root@linux-87-01 ~]# echo "$UID"
0
[root@linux-87-01 ~]#
反引号、不加引号:
[root@linux-87-01 ~]# echo `hostname`
linux-87-01
[root@linux-87-01 ~]# echo {1..3}.txt
1.txt 2.txt 3.txt
1.2 重定向符号
重定向符号:>、>>
> :其实是1>,一般可以省略1(1:数字1)。正确的标准输出重定向
>>:其实是1>>,一般可以省略1。正确的标准追加输出重定向
2>:错误输出重定向
2>>:错误输出追加重定向
例如:
[root@linux-87-01 ~]# echo 11 > 1.txt
[root@linux-87-01 ~]# echo 22 >> 1.txt
[root@linux-87-01 ~]# cat 1.txt
11
22
[root@linux-87-01 ~]#
错误输出:
[root@linux-87-01 ~]# hah 2> 1.txt
[root@linux-87-01 ~]# cat 1.txt
-bash: hah: command not found
[root@linux-87-01 ~]# zzzz 2>> 1.txt
[root@linux-87-01 ~]# cat 1.txt
-bash: hah: command not found
-bash: zzzz: command not found
[root@linux-87-01 ~]#
正确、错误输出都输出到同一个文件。:
#写法1
[root@linux-87-01 ~]# 3333 1>>1.txt 2>>1.txt
#写法2
[root@linux-87-01 ~]# 3333 1>>1.txt 2>&1
#写法3
[root@linux-87-01 ~]# 3333 &>>1.txt
小结:
重定向符号 | 含义 | 应用场景 |
---|---|---|
>或1> | 标准输出重定向:先清空文件,然后写入 | 大部分情况下先清空的时候使用 |
>>或1>> | 标准输出追加重定向:直接写到文件末尾 | 修改配置文件,表示追加的时候使用 |
2> | 标准错误输出重定向:先清空文件,然后写入错误信息 | 较少单独使用 |
2>> | 标准错误输出追加重定向:直接把错误信息写到文件末尾 | 较少单独使用 |
命令>>文件2>&1 | 无论对错,都把结果写入文件 | 比较常用 |
命令&>>文件 | 无论对错,都把结果写入文件 | 比较常用 |
<或0< | 标准输入重定向 | 比较少用 |
<<或0<< | 标准输入追加重定向 | 与cat命令搭配使用 |
输入重定向很少用。
案例:<<与cat使用
[root@linux-87-01 ~]# cat >2.txt<<EOF
> 1
> 2
> 3
> EOF
[root@linux-87-01 ~]# cat 2.txt
1
2
3
[root@linux-87-01 ~]#
<<与cat使用格式:
格式1:
cat >文件<<结束标记
格式2:
cat <<EOF >文件
EOF:结束标记,End Of File
结束标记两边不能有多余符号
1.3 通配符
通配符,常用于Linux中大部分命令
符号 | 含义 |
---|---|
* | 表示所有 |
{} | 列出序列,与echo、touch、mkdir使用 |
[] | 参考正则中的含义即可 |
[!]、[^] | 取反 |
? | 任意一个字符 |
案例:{}使用
[root@linux-87-01 ~]# echo {1..3}
1 2 3
[root@linux-87-01 ~]# echo 1.txt{,.bak}
1.txt 1.txt.bak
[root@linux-87-01 ~]# echo {1..10..2}
1 3 5 7 9
2、正则
正则本质是一些符号:^、$、^$、*等
2.1、正则与通配符的区别
正则 | 匹配文件内容(匹配字符) | 三剑客、开发语言 |
---|---|---|
区别 | 用途(找的内容不同) | 支持的命令不同 |
通配符 | 匹配文件名(命令参数) | Linux大部分命令都支持 |
2.2、正则分类
分类 | 符号 |
---|---|
基础正则 | ^ 、$、 ^$、 . 、* 、.*、 [] 、[^] |
扩展正则 | | 、+、 () 、{} 、? |
查看文件内容及隐藏的符号:cat -A 文件名
1)基础正则
案例1:查找/etc/passwd文件中以ro开头和以nologin结尾的内容
[root@linux-87-01 ~]# grep '^ro' /etc/passwd
[root@linux-87-01 ~]# grep 'nologin$' /etc/passwd
grep -n:可以显示行号,例如:
[root@linux-87-01 ~]# grep -n '^$' /etc/selinux/config
1:
13:
14:
[root@linux-87-01 ~]#
1)^:以什么开头
2)$:以什么结尾
3)^$:过滤空白行
案例2:排除etc/ssh/sshd_config文件中空白行和以#开头的行
[root@linux-87-01 ~]# grep -v '^$' /etc/ssh/sshd_config | grep -v '^#'
4)点(.):表示任意一个字符,不匹配空行
grep -o选项:显示正则匹配到了什么,显示执行过程
5)\:转义字符
6)*:前一个字符连续出现0次或0次以上
[root@linux-87-01 ~]# echo 12345 | grep '5*'
12345
[root@linux-87-01 ~]# echo 12345 | grep -o '5*'
5
[root@linux-87-01 ~]#
正则的贪婪性:表示连续出现或所有的时候,正则表现出贪婪性,也就是尽可能匹配得多
7).*:所有,任意字符。
.:表示任意一个
*:表示前一个字符连续出现0次或0次以上
.*:表示所有
例如:
[root@linux-87-01 ~]# grep -n '^.*root' /etc/passwd
1:root:x:0:0:root:/root:/bin/bash
10:operator:x:11:0:operator:/root:/sbin/nologin
[root@linux-87-01 ~]#
8)[]:表示匹配任意1个字符。
比如,[abc]表示匹配a或b或c,即abc中的任意1个
[root@linux-87-01 ~]# echo 12345 | grep '[123]'
12345
[root@linux-87-01 ~]#
[a-z]:a到z的任意1个
[0-9]:0到9
[a-zA-Z]:a到z的任意1个大小写
[a-Z]:a到z的任意1个大小写
[0-Z]:数字、a到Z
案例1:匹配出/etc/passwd文件中以m或n开头的行
[root@linux-87-01 ~]# grep '^[mn]' /etc/passwd
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
[root@linux-87-01 ~]#
9)[^]、[^abc]:表示匹配任意1个字符,排除abc,中括号相当于1个字符
小结:
基础正则 | 含义 |
---|---|
^ | 以什么开头 |
$ | 以什么结尾 |
^$ | 空行 |
. | 任意一个字符 |
\ | 转义字符 |
* | 前一个字符出现0次或0次以上 |
.* | 所有 |
[] | [abc]:a或b或c,[]相当于是1个字符 |
[^] | [^abc]:匹配除了abc以外的内容,[]相当于是1个字符 |
2)扩展正则
egrep或grep -E支持扩展正则
sed使用sed -r支持扩展正则
awk默认支持扩展正则
1)+:前一个字符连续出现1次或1次以上
#3种写法
[root@linux-87-01 ~]# grep -E 'o+' /etc/passwd
[root@linux-87-01 ~]# grep 'o\+' /etc/passwd
[root@linux-87-01 ~]# egrep 'o+' /etc/passwd
[root@linux-87-01 ~]# echo http https | grep -E 'https+'
http https
[root@linux-87-01 ~]#
例如:+与[]使用
[root@linux-87-01 ~]# echo 12345 | grep -E '[0-9]+'
12345
[root@linux-87-01 ~]#
2)|:或者
[root@linux-87-01 ~]# echo 12345 | grep -E '2|3'
12345
[root@linux-87-01 ~]#
3)():表示一个整体,用于后向引用(反向引用sed)
例如:检查系统中tree、vim软件是否安装
[root@linux-87-01 ~]# rpm -qa | grep -E '^(tree|vim)'
vim-common-7.4.629-8.el7_9.x86_64
vim-minimal-7.4.629-7.el7.x86_64
vim-filesystem-7.4.629-8.el7_9.x86_64
vim-enhanced-7.4.629-8.el7_9.x86_64
[root@linux-87-01 ~]#
4){}:用法:a{n,m}表示a字符连续出现至少n次,最多m次
[root@linux-87-01 ~]# echo 1122223 | grep -E '2{1,2}'
1122223
[root@linux-87-01 ~]#
a{n}:前一个字符a连续出现n次
a{n,}:前一个字符a连续出现至少n次
a{,m}:前一个字符a连续出现最多m次
身份证号码匹配:
地区: [1-9]\d{5} \d:表示数字
年的前两位: (18|19|([23]\d)) 1800-2399
年的后两位: \d{2}
月份: ((0[1-9])|(10|11|12))
天数: (([0-2][1-9])|10|20|30|31) 闰年不能禁止29+
三位顺序码: \d{3}
两位顺序码: \d{2}
校验码: [0-9Xx]
正则表达式:
十八位: ^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$
十五位: ^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}$
总:
( ^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}$)
ip地址匹配:
[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\ #但并不完美,无法精确匹配0-255
0-99 : ^[0-9]{1,2}$
1开头:100-199 ^1[0-9]{2}$
2开头:200-249 ^2[0-4][0-9]$
2开头:250-255 ^25[0-5]$
grep -Ew:w,精确匹配
5)?:前一个字符出现0次或1次
[root@linux-87-01 ~]# echo http https | grep -E 'https?'
http https
[root@linux-87-01 ~]#
匹配指定后缀的域名:
^(https?://)?.*(\.com|\.cn|\.com.cn)$
小结:
扩展正则 | 含义 |
---|---|
| | 或者 |
+ | 前一个字符连续出现1次或多次 |
() | 1、表示一个整体,2、用于后向引用(反向引用sed) |
{} | a{n,m}表示字符a连续出现至少n次,最多m次 |
? | 前一个字符出现0次或1次 |
3、grep
grep的选项:
-v 排除、取反
-n 显示行号
-E 支持正则,grep -E 等于 egrep
-o 显示过程、显示正则匹配到了什么
-w 精确匹配
-i 过滤的时候不区分大小写
-P 支持perl语言的正则
精确匹配:
[root@linux-87-01 ~]# echo abc 1abcd | grep -w 'abc'
abc 1abcd
[root@linux-87-01 ~]# echo abc 1abcd | grep '\babc\b'
abc 1abcd
[root@linux-87-01 ~]# echo abc 1abcd | grep '\<abc\>'
abc 1abcd
[root@linux-87-01 ~]#
4、sed
4.1 三剑客对比
三剑客 | 通用 | 应用场景 |
---|---|---|
grep、egrep | 过滤 | 擅长过滤 |
sed | 过滤 | 替换,精确过滤(取行) |
awk | 过滤 | 取列,统计与计算 |
4.2 sed核心功能
增删改查
查(过滤)
改(替换)
删除
增加
案例01:显示/etc/passwd文件的第3行
[root@linux-87-01 ~]# sed -n '3p' /etc/passwd
选项:
-n :取消默认输出,sed默认情况下会把文件内容都输出。一般在使用p的时候,使用-n
'3p':表示找谁干啥
找谁:条件 找行,3表示第3行
干啥:动作 p(print)显示
案例02:显示/etc/passwd文件的3-5行内容
[root@linux-87-01 ~]# sed -n '3,5p' /etc/passwd
案例03:过滤出/etc/passwd文件以bash结尾的行
#使用grep
[root@linux-87-01 ~]# grep 'bash$' /etc/passwd
#使用sed
[root@linux-87-01 ~]# sed -nr '/bash$/p' /etc/passwd
选项:
-r :表示支持正则
'//p':类似于grep功能
案例04:在日志中过滤,根据时间范围过滤某一天的11:05:00到11:07:00的日志
假设日志文件为:access.log,第4列为时间,格式为:[22/Nov/2015:11:02:00 +0800]
sed -n ‘/从哪里来/,/到哪里去/p’ 文件
sed -n ‘/ /,/ /p’ 文件
[root@linux-87-01 ~]# sed -n '/11:05:00/,/11:07:00/p' access.log
sed查找功能小结:
类似于grep、egrep过滤
sed可以指定行号,某一个,连续多行内容
sed可以grep、egrep过滤,sed -n '//p' 文件名
sed可以过滤范围的内容(比如,日志通过日期范围)
案例01:修改 /etc/selinux/config文件的SELINUX=enforcing为SELINUX=disabled
[root@linux-87-01 ~]# sed 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config
执行结果并没有修改文件,必须加上-i选项:
[root@linux-87-01 ~]# sed 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config
也可以修改某行:
sed -i 'ns###g' 文件
其中,
n为第n行,s为substitute(替换),
g为global(全局),也就是全部替换,否则只替换每一行的第1个内容,
#为分隔符,可以自定义,如/、@等等
替换前先备份再修改:
sed -i.bak 's###g' 文件
选项说明:
-n 取消默认输出,sed默认情况下会把文件内容都输出。一般在使用p的时候,使用-n
-r 支持扩展正则
-i 修改文件内容,替换的时候用。如果有多个选项,要放在所有选项最后
-i.bak 先备份,再修改
一般地,不建议直接-i,先确保正确,才用-i做最后修改。
4.5 删除功能
d:delete,按照行为单位删除(相当于grep -v)
案例01:排除/etc/ssh/sshd_config文件的空行和注释行
# 使用egrep
[root@linux-87-01 ~]# egrep -v '^$|#' /etc/ssh/sshd_config
#使用sed
[root@linux-87-01 ~]# sed -r '/^$|#/d' /etc/ssh/sshd_config
这里源文件并没有实际删除
4.6 增加功能
如:
[root@linux-87-01 ~]# seq 5 | sed '3a haha'
1
2
3
haha
4
5
[root@linux-87-01 ~]#
3a haha:表示在第3行下面添加haha内容,haha就为第4行了
3i :则表示第3行上面面添加
3c:则表示把第3行替换
选项解释:
a:append,在指定行下面追加内容
i:insert,在指定行上面追加内容
c:replace,替换指定行内容
4.7 反向引用
一般用于对数据进行加工
需求:比如,要在12345的两边分别加上<>,变成<12345>
[root@linux-87-01 ~]# echo 12345 | sed -r 's#([0-9]+)#<\1>#g'
<12345>
[root@linux-87-01 ~]#
解释:
([0-9]+):用()分组
\1:表示1组
如果要:12-34-56则:
[root@linux-87-01 ~]# echo 123456 | sed -r 's#(..)(..)(..)#\1-\2-\3#g'
12-34-56
[root@linux-87-01 ~]#
案例1:把/etc/passwd文件复制到/root目录中,然后把该文件的第1列和最后1列调换
[root@linux-87-01 ~]# cp /etc/passwd .
/etc/passwd文件内容格式如下:
root:x:0:0:root:/root:/bin/bash
以:为分隔符,共7列,根据题意,调换1、7列,可以分三组,第1列为第1组,最后1列为第3组,剩下的为第2组。
使用()分组
[root@linux-87-01 ~]# sed -r 's#^(.*)(:x:.*:)(/.*$)#\3\2\1#g' passwd
重点是:怎么写正则,然后分组。
4.8 选项小结
-n 取消默认输出,sed默认情况下会把文件内容都输出。一般在使用p的时候,使用-n
-r 支持扩展正则
-i 修改文件内容,替换的时候用。如果有多个选项,要放在所有选项最后
-i.bak 先备份,再修改
案例:使用sed命令取出ip地址
使用ip a s eth0或ip addr show eth0都可以查看eth0网卡的ip地址
[root@linux-87-01 ~]# ip a s eth0 | sed -n '3p' | sed -r 's#^.*et (.*)/.*$#\1#g'
192.168.10.100
[root@linux-87-01 ~]#
5、awk
5.1 取列功能
awk默认以空格分隔
案例01:ll /etc/取出第1、5列和最后一列
[root@linux-87-01 ~]# ll /etc/ | awk '{print $1,$5,$NF}
参数:
$NF:最后1列
NF:Number of Fields,每一行多少列
$1:第1列
$5:第5列
案例02:取出/etc/passwd中的第1列、最后1列,倒数第二列
[root@linux-87-01 ~]# awk -F ':' '{print $1,$NF,$(NF-1)}' /etc/passwd
选项:
-F:指定分隔符,只要不是用空格作为分隔符的时候,就使用-F指定。支持正则
案例03:取出ip
#以空格或/为分隔符
#ip a s eth0的结果,inet的前面有4个空格
[root@linux-87-01 ~]# ip a s eth0 | sed -n '3p' | awk -F'[ /]+' '{print $3}'
192.168.10.100
[root@linux-87-01 ~]# ip a s eth0 | awk 'NR==3' | awk -F'inet |/24' '{print $2}'
192.168.10.100
[ /]+的说明:
[ /]:仅会一个一个匹配空格或/,结合-F,就会遇到1个空格或/就会分隔1次
[ /]+:则会匹配连续出现的空格或/,这样多个连续的空格只会被-F分隔1次
选项:
-F;指定分隔符
NR:行号
案例05:取出stat /etc/hosts结果的权限
[root@linux-87-01 ~]# stat /etc/hosts | sed -n '4p' | awk -F'[(/]' '{print $2}'
0644
[root@linux-87-01 ~]#
5.2 取行功能
·行号:一行、多行
·过滤://
·做比较
案例1:取出/etc/passwd中的指定行
NR:Mumber of Record
#1、取出第1行
[root@linux-87-01 ~]# awk 'NR==1' /etc/passwd
#2、取出3到最后一行
[root@linux-87-01 ~]# awk 'NR>=3' /etc/passwd
#3、取出3到5行
[root@linux-87-01 ~]# awk 'NR>=3 && NR<=5' /etc/passwd
awk比较符号:
== 等于
!= 不等于
> 大于
>= 大于等于
< 小于
<= 小于等于
逻辑符号:
&& :并且
||:或者
案例02:根据某一列内容进程判断并取行
如果/etc/passwd的第三列数字大于999,则显示这一行
[root@linux-87-01 ~]# awk -F':' '$3>999' /etc/passwd
案例03:显示磁盘已用5%以上的行
[root@linux-87-01 ~]# df -h | awk -F'[ %]+' '$5 >= 5'
案例04:过滤出包含root或sshd的行
#使用awk
[root@linux-87-01 ~]# awk '/root|sshd/' /etc/passwd
#使用grep
[root@linux-87-01 ~]# grep -E 'root|sshd' /etc/passwd
案例05:范围过滤
与sed类似,例如:
#使用awk
[root@linux-87-01 ~]# seq 10 | awk '/3/,/5/'
3
4
5
[root@linux-87-01 ~]#
#使用sed
[root@linux-87-01 ~]# seq 10 | sed -n '/3/,/5/p'
3
4
5
[root@linux-87-01 ~]#
案例06:如果/etc/passwd中的第3列是以0或1开头的,则显示出该行
[root@linux-87-01 ~]# awk -F':' '$3 ~ /^[01]/' /etc/passwd
$数字 ~ /xxx/:某一列包含xxx内容
案例07:过滤出access.log中的第7列以.jpg或.gif结尾的行数
假设access.log文件分隔符为:空格
[root@linux-87-01 ~]# awk '$7 ~ /(.ipg|.gif)$/' access.log | wc -l
[root@linux-87-01 ~]# awk '$7 ~ /.ipg$|.gif$/' access.log | wc -l
取行小结:
1、根据行号,如:NR==1,NR>2
2、根据内容,如:/ xxx /
3、某一列包含xxx内容,$3 ~ /xxx/
4、比较某一列大于、小于、等于xxx内容,如:$3>999
5.3 行列组合
比如先取行,再取列。
格式:
awk格式 | 选项 | 找谁{干啥}’ | 文件(参数) |
---|---|---|---|
awk格式 | -F’:’ | ‘NR==1{print $1}’ | /etc/passwd |
‘条件{动作}’ 条件:找哪一行 动作:输出某几列 |
案例01:取出ip地址
[root@linux-87-01 ~]# ip addr | grep eth0 | awk 'NR==2' | awk -F'[ /]+' '{print $3}'
192.168.10.100
[root@linux-87-01 ~]# ip addr | grep eth0 | awk -F'[ /]+' 'NR==2{print $3}'
192.168.10.100
[root@linux-87-01 ~]#
案例02:取出当前系统swap占用大小
top、free都可以查看swap使用情况
[root@linux-87-01 ~]# free | awk 'NR==3{print $3}'
[root@linux-87-01 ~]# top -bn1 | awk 'NR==5{print $7}'
top选项:
n:更新的次数,完成后将会退出 top
b:批次档模式,搭配 "n" 参数一起使用
-bn1:就是更新1次,然后退出top命令
5.3 统计与计算
案例01:统计系统内存空闲率
可用内存÷总内存
[root@linux-87-01 ~]# free | awk 'NR==2{print $NF/$2*100"%"}'
84.9413%
[root@linux-87-01 ~]#
案例02:统计/etc/services中空行的数量
#1、使用grep
[root@linux-87-01 ~]# grep -E '(^$)' /etc/services | wc -l
#2、使用awk
[root@linux-87-01 ~]# awk '/^$/' /etc/services | wc -l
#3、awk方法2
[root@linux-87-01 ~]# awk '/^$/{i=i+1;print i}' /etc/services
#使用END
[root@linux-87-01 ~]# awk '/^$/{i=i+1}END{print i}' /etc/services
i=i+1可以写成:i++
END{内容},END{}里面的内容会在awk读取完成文件内容后运行
END{}一般用于输出最终的结果
案例03:求出num.txt文件中每一行数字的总和
先创建num.txt文件:
[root@linux-87-01 ~]# seq 10 > num.txt
求和:
[root@linux-87-01 ~]# awk '{i=i+$1} END{print i}' num.txt
55
[root@linux-87-01 ~]#
num.txt文件有10行,每行只有1列,所以:i=i+$1
案例04:计算1到100的总和
[root@linux-87-01 ~]# seq 100 | awk '{i=i+$1}END{print i}'
5050
[root@linux-87-01 ~]#
案例05:统计access.log文件第10列的总和
access.log文件第10列的单位是字节
[root@linux-87-01 ~]# awk '{i=i+$10}END{print i/1024/1024/1024}' access.log
2.30828
[root@linux-87-01 ~]#
除以三个1024,结果就是GB了