正则表达式

3 篇文章 0 订阅

正则表达式RE

1.正则表达式(regular expression, RE)是一种字符模式,用于在查找过程中匹配指定的字符。
2.在大多数程序里,正则表达式都被置于两个正斜杠之间;例如/l[oO]ve/就是由正斜杠界定的正则表达式,它将匹配被查找的行中任何位置出现的相同模式。在正则表达式中,元字符是最重要的概念。
 
#正则表达式分为:
正则表达式基本元字符 
正则表达式拓展元字符
​
元字符使正则表达式具有处理能力。所谓元字符就是指那些在正则表达式中具有特殊意义的专用字符,可以用来规定其前导字符(即位于元字符前面的字符)在目标对象中的出现模式。

元字符

用于控制正则表达式的结构和行为,如重复、选择、位置匹配等。

正则表达式基本元字符

元字符
示例               功能                               示例
^               匹配字符串的开始位置                  ^love 
$               匹配字符串的结束位置                  love$ 
.               匹配除换行符外的任何单个字符                 l..e  
*               匹配前导符零到多次            ab*love 匹配以 "a" 开头,紧跟着零个或多个 "b",然后是 "love" 的字符串
.*              匹配任意多个字符(贪婪匹配)       Client.* 匹配以“Client”开头的任意字符
[]              匹配方括号中任意一个字符(定义一个字符集)      [lL]ove
[ - ]           匹配指定范围内的一个字符      [a-z0-9]ove             
[^]             匹配不在指定组里的字符        [^a-z0-9]ove
\               用来转义元字符               love\.
\<              词首定位符                  \<love
\>              词尾定位符                  love\>

正则表达式拓展元字符

扩展正则表达式元字符             功能                  示例
+                       匹配一次或多次前导字符        [a-z]+ove
?                       匹配零次或一次前导字符        lo?ve
a|b                     匹配a或b                    love|hate
x{m}                    字符x重复m次                o{5}
x{m,}                   字符x重复至少m次             o{5,}
x{m,n}                  字符x重复m到n次              o{5,10}
()                      定义一个字符组               ov+ (ov)+

预定义字符类 

匹配特定类型的字符,如数字、字母、空白等,简化了常见字符集的书写,使得正则表达式更简洁

正则表达式中常用的预定义字符类包括:
\d 和 \D:
\d:匹配任何数字字符,等同于 [0-9]。
\D:匹配任何非数字字符,等同于 [^0-9]。
\w 和 \W:
\w:匹配任何“单词”字符,即字母、数字或下划线,等同于 [a-zA-Z0-9_]。
\W:匹配任何非“单词”字符,等同于 [^a-zA-Z0-9_]。
\s 和 \S:
\s:匹配任何空白字符,如空格、制表符、换行符等。
\S:匹配任何非空白字符。
\b 和 \B:
\b:匹配一个单词边界,即单词字符和非单词字符之间的位置。
\B:匹配非单词边界的位置。

示例

(1)匹配数字
    \d+ :匹配一个或多个连续的数字。
(2) 匹配电子邮件地址:
 \b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b
    \b:单词边界,确保电子邮件地址不是其他单词的一部分。
    [A-Za-z0-9._%+-]:匹配用户名部分的任何字母、数字或字符 ._%+-。
    +:表示前面的模式至少出现一次,但可以出现多次。
    @:匹配电子邮件地址中的 @ 符号。
    [A-Za-z0-9.-]+:匹配域名部分的任何字母、数字或字符 . -。
    \.:匹配电子邮件地址中的点号。
    [A-Z|a-z]{2,}:匹配顶级域名(如 .com, .org 等),至少两个字母。
    \b:单词边界。
(3) 匹配URL
https?:\/\/[\w.\/-]+  匹配以 http 或 https 开头的 URL
    https?:匹配 http 或 https,其中 ? 表示 s 可选。
    :\/\/:匹配 :// 字符串。
    [\w.\/-]+:匹配 URL 中的任何字母、数字、下划线、点号、斜杠或破折号
(4)匹配日期格式
 \d{4}-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01]) 匹配 YYYY-MM-DD 格式的日期
    \d{4}:匹配四位数字,通常是年份。
    -(0?[1-9]|1[012]):匹配月份,范围为 01 到 12。
    0?[1-9]:匹配 01 到 09。
    1[012]:匹配 10 到 12。
    0?[1-9]:匹配 01 到 09。
    [12][0-9]:匹配 10 到 29。
    3[01]:匹配 30 和 31。

正则判断

 
运用正则,判断需要[[ ]]
=~ 操作符判断字符串是否匹配右侧指定的正则表达式,一般放在[[]]中判断
# num1=1
# [[ $num1 =~ ^[0-9]+$ ]] && echo "yes" || echo "no"
yes
注意:^在[]内表示取反,^在[]外表示以什么开头
# num3=1b1 
# [[ $num3 =~ ^[0-9]+$ ]] && echo "yes" || echo "no"
no
# num=1.6
# [[ $num =~ ^[0-9]\.[0-9]+$ || $num =~ ^[0-9]+$ ]] && echo "yes" || echo "no"       
yes

grep全局的正则

grep命令是Globally search a Regular Expression and Print的缩写,表示进行全局的正则匹配并进行打印。grep的相关扩展命令egrep其中egrep支持更多的正则匹配。

grep使用

# grep '^#' /etc/ssh/ssh_config     #过滤以#号开头的行
# grep -v '^#' /etc/ssh/ssh_config  #-v:取反,表示反向查找
# grep 'sendenv' /etc/ssh/ssh_config 
# grep -i 'sendenv' /etc/ssh/ssh_config  #-i忽略大小写
# grep  'bash' /opt/test/ #过滤某个目录下面带有bash的行
# grep  -r 'bash' /opt/test/  #-[r|R]表示递归查询

正则过滤

基本正则匹配--grep
(1)\< 词首定位符号      \>词尾定位符号
# cat jack.txt 
Jack JACK JAck jackly jack
:% s/\<[Jj]ack\>/123/g

(2)^  以什么开头
# grep '^root' /etc/passwd
root:x:0:0:root:/root:/bin/bash
​
(3)$以什么结尾
# grep 'bash$' /etc/passwd
root:x:0:0:root:/root:/bin/bash
confluence:x:1000:1000:Atlassian Confluence:/home/confluence:/bin/bash 
to:x:1003:1003::/home/to:/bin/bash
​
(4). 匹配单个字符
# grep 'r..t' /etc/passwd 
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 
dockerroot:x:998:995:Docker User:/var/lib/docker:/sbin/nologin 
# grep 'r.t' /etc/passwd 
operator:x:11:0:operator:/root:/sbin/nologin 
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
​
(5).* 任意多个字符
# grep 'r.*t' /etc/passwd 
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 
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin polkitd:x:999:997:User for polkitd:/:/sbin/nologin postfix:x:89:89::/var/spool/postfix:/sbin/nologin 
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin dockerroot:x:998:995:Docker User:/var/lib/docker:/sbin/nologin 
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
abrt:x:1041:1041::/home/abrt:/bin/bash
​
(6)[] 匹配方括号中的任意一个字符
# useradd Root
# grep 'Root' /etc/passwd
# grep '[Rr]oot' /etc/passwd 
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
Root:x:1000:1000::/home/Root:/bin/bash
​
​
(7)[ - ] 匹配指定范围内的一个字符
# grep [a-z]oot /etc/passwd  #a-z
root:x:0:0:root:/root:/bin/bash 
operator:x:11:0:operator:/root:/sbin/nologin 
dockerroot:x:998:995:Docker User:/var/lib/docker:/sbin/nologin
​
(8)[^] 匹配不在指定组内的字符 #注意:^在[]内表示取反,^在[]外表示以什么开头
# grep '[^0-9]' /etc/passwd 
​
# grep '[^0-9A-Z]oot' /etc/passwd 
root:x:0:0:root:/root:/bin/bash 
operator:x:11:0:operator:/root:/sbin/nologin 
dockerroot:x:998:995:Docker User:/var/lib/docker:/sbin/nologin
扩展正则匹配---egrep
扩展正则表达式元字符             功能                  示例
+                       匹配一次或多次前导字符         [a-z]+ove
?                       匹配零次或一次前导字符         lo?ve
a|b                     匹配a或b                      love|hate
x{m}                    字符x重复m次                   o{5}
x{m,}                   字符x重复至少m次,没有上限      o{5,}
x{m,n}                  字符x重复m到n次                o{5,10}
x{,m}                   字符x最多出现m次,没有下限      o{,10}
()                      字符组                         ov+ (ov)+
​
egrep 支持正则表达式的拓展元字符
# egrep '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' /etc/resolv.conf 
nameserver 192.168.246.2
​
+ 匹配一个或多个前导字符
# egrep 'ro+t' /etc/passwd 
root:x:0:0:root:/root:/bin/bash 
operator:x:11:0:operator:/root:/sbin/nologin 
dockerroot:x:998:995:Docker User:/var/lib/docker:/sbin/nologin
​
a|b    匹配a或b
# netstat -anlp|egrep ':80|:22'
# egrep 'root|jack' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
jack1:x:1001:1001::/home/jack1:/bin/bash
jack2:x:1002:1002::/home/jack2:/bin/bash
​
x{m} 字符x重复m次 
# cat a.txt
love
love.
loove
looooove 
# egrep 'o{2}' a.txt
loove
looooove 
# egrep 'o{2,}' a.txt
loove
looooove 
# egrep 'o{6,7}' a.txt

shell 编程-SED


stream editor(流编辑器,sed)是一种在线非交互式编辑器,用于过滤和转换文本数据流。可以自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等非交互式编辑器,一次处理一行内容。

支持正则表达式
    与grep一样,sed在文件中查找模式时也可以使用正则表达式(RE)和各种元字符,用于查找和替换,以下是sed支持的元字符:
使用基本元字符集    ^, $, ., *, [], [^], \< \>
使用扩展元字符集    ?, +, { }, |, ( )

sed基本用法

语法

sed [选项] '命令' [文件]
[选项]:可选的命令行选项。
'命令':包含 sed 指令的脚本。
[文件]:指定要处理的文件。如果省略,则从标准输入读取。
常见选项
-r:使用扩展正则表达式
-e:它告诉sed将下一个参数解释为一个sed指令,只有当命令行上给出多个sed指令时才需要使用-e选项
-f:后跟保存了sed指令的文件
-i:直接对内容进行修改,不加-i时默认只是预览,不会对文件做实际修改
-n:取消默认输出,sed默认会输出所有文本内容,使用-n参数后只显示处理过的行

基本命令
s/old/new/flags:查找及替换命令。将每一行中首次出现的 old 替换成 new。
flags:可选标志,例如 g 表示全局替换(即替换每一行中所有匹配项),p 表示打印修改后的行。
a\text:在当前行后面添加 text。
i\text:在当前行前面插入 text。
c\text:用 text 替换当前行。
p:打印当前行。
d:删除当前行。

打印

sed 默认会输出文件的每一行,无论这行内容是否能匹配上匹配模式。

语法:
sed [-p] -r '匹配内容'  file_name
-r:支持扩展正则,在实际使用的时候,都会加上 -r 参数,即使没有用的扩展正则也不会有任何影响。
-p默认可以不加
-r 允许使用 ?, +, {}, |, 和 () 等特殊字符,而不需要转义。

搜索替换

sed会自动打印文件的每一行,同时查找模式匹配的行,找到后执行后面的命令,默认是 p 打印(不加 -n 的情况下)

s查找替换
sed -r 's/sync/sync222/' /etc/passwd   #每一行中替换第一个匹配内容 
sed -r '4s/sbin/999/' /etc/passwd      #指定第四行替换内容
g全局替换   
sed -r 's/sync/sync222/g' /etc/passwd  #全局替换(每一行中替换所有匹配内容)
i忽略大小写
sed -r 's/net/net555/gi' /etc/passwd   #全局替换,忽略大小写
​-n静默输出(不打印默认输出)
sed  -r -n 's/sync/sync222/' /etc/passwd

多重编辑选项

1.使用多重指令:-e  给予sed多个命令的时候需要-e选项
# sed -r -e 's/bin/666/' -e 's/sbin/999/' /etc/passwd
2.使用脚本文件:当有多个要编辑的项目时,可以将编辑命令放进一个脚本里,再使用sed搭配-f选项 
-f <script文件> 以选项中指定的script文件来处理输入的文本文件。
# vim s.sed
s/root/root111/ 
s/bin/bin222/g 
4s/nologin/nologin222/ 
s/games/games555/ 
# sed -f s.sed /etc/passwd #使用s.sed内的命令编辑
# sed -f s.sed /etc/passwd > newfile.txt #编辑并重定向输出保存

定址编辑

地址用于决定对哪些行进行编辑。地址形式可以是数字、正则表达式或二者的结合。如果没有指定地址,sed将处理输入文件中的所有行。

sed -r '1d' passwd     #删除文件的第1行 
sed -r '1,5d' passwd   #删除文件的第1到5行
sed -r '2,$d' passwd     #删除第2行到最后一行
sed -r '/^root/d' passwd    #匹配到root开头的行,删除此行
sed -r '/root/d' passwd  #含有root的行都删除
sed -r '/bash/,3d' passwd  #匹配到bash行,从此行删除到第3行
sed -r '1~2d' passwd   #删除奇数行,间隔两行删除
sed '0~2d' passwd      #删除偶数行,从0开始间隔2行删除

插入修改

1.行前插入 i
sed -r '2i\abc' /etc/passwd  #指定在第2行前插入
2.追加命令 a
sed -r '2a\abc' /etc/passwd  ##指定在第2行后插入
sed -r -e '$ a\333' -e "333" passwd #在末行插入,a可以在指定的行之后追加文本
3.修改命令 c
sed -r '4c\asfasdf' /etc/passwd   
sed -r '4c\111\'    #将第4行的内容替换为111。在替换后的内容后面追加两行文本:aaa和bbb     
> aaa\
> bbb' passwd
sed -r '7c\SELINUX=disabled' /etc/sysconfig/selinux   #关闭selinux
​3.-i 用于直接编辑文件
sed -r -i '7c\SELINUX=disabled' /etc/sysconfig/selinux #关闭selinux
sed -ri 's/^SELINUX=.*/SELINUX=disabled/' /etc/sysconfig/selinux #关闭selinux
sed -r -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/sysconfig/selinux #关闭selinux
​
4.使用-i参数比较危险, 最好使用时在后面加上.bak就会产生一个备份的文件,以防后悔
sed -r -i.bak 's/root/ROOT/' passwd
sed应用:增删注释
cp /etc/ssh/ssh_config . 
1.删除配置文件中 # 号注释的行
sed -ri '/^#/d' ssh_config
2.给文件行添加注释:
sed -r '2,5s/^/#/' passwd
给所有行添加注释:
sed -r 's/^/#/' passwd
3.给文件行添加和取消注释
sed -ri s/^#baseurl/baseurl/g /etc/yum.repos.d/CentOS-Base.repo
sed -r s/^mirrorlist/#mirrorlist/g /etc/yum.repos.d/CentOS-Base.repo

shell编程之awk

  • awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自一个或多个文件,或其它命令的输出。可以在命令行中使用,但更多是作为脚本来使用。
  • awk的处理文本和数据的方式是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行操作。如果没有指定模式,则所有被操作所指定的行都被处理。
  • awk分别代表其作者姓氏的第一个字母。因为它的作者是三个人,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。
awk处理过程: 依次对每一行进行处理,然后输出,默认分隔符是空格或者tab键 

awk的形式语法格式

awk [options] 'commands' filenames
[options]
-F 对于每次处理的内容,指定一个自定义的输入字段分隔符
默认的分隔符是空白字符(空格或 tab 键 )

awk工作原理

awk -F":" '{print $1,$3}' /etc/passwd
(1)awk使用一行作为输入,并将这一行赋给变量$0,每一行可称作为一个记录,以换行符结束 
(2)行被空格分解成字段,每个字段存储在已编号的变量中,从$1开始
command:
BEGIN{}                   {}               END{}         filename
行处理前的动作          行内容处理的动作     行处理之后的动作    文件名
BEGIN{}和END{} 是可选项。
BEGIN{}:读入文本之前要操作的命令。
{}:主输入循环:用的最多。读入文件之后擦操作的命令。如果不读入文件都可以不用写。
END{}:文本全部读入完成之后执行的命令。
示例
awk 'BEGIN{print 1/2} {print "ok"} END{print "----"}' /etc/hosts
或者:
cat /etc/hosts | awk 'BEGIN{print 1/2} {print "ok"} END{print "----"}'
0.5
ok
ok

记录和字段

awk 按记录处理:
一行是一条记录,因为awk默认以换行符分开的字符串是一条记录。(默认\n换行符:记录分隔符)
字段:
以字段分割符分割的字符串,默认是单个或多个" " tab键。

awk变量

$0        表示当前行的内容
NF        统计字段的个数
$NF       是number finally,表示最后一列的信息
RS        输入记录分隔符;
ORS       输出记录分隔符。
NR        打印记录号,(行号)
FNR       可以分开,按不同的文件打印行号。
FS        输入字段分隔符,默认为一个空格。  
OFS       输出的字段分隔符,默认为一个空格。 
FILENAME  被处理的文件名
$1,$2...  第一个字段,$2第二个字段,依次类推...
实战
FS(输入字段分隔符)---简写为-F(属于行处理前) 不加-F默认为空格区分!
cat /etc/passwd | awk 'BEGIN{FS=":"} {print $1,$2}'
cat /etc/passwd | awk -F":" '{print $1,$2}'
二者效果相同:打印/etc/passwd文件的每一行的用户名和用户的密码
从 /etc/passwd 文件中读取每一行,并将每一行按冒号分割成多个字段。只打印每一行的第一列(用户名)和第二列(密码哈希),忽略其他字段。

OFS(输出字段分隔符)
cat /etc/passwd | awk 'BEGIN{FS=":";OFS=".."} {print $1,$2}'
awk 'BEGIN{FS=":"}''{print $1".."$2}' /etc/passwd 
#二者效果相同:打印/etc/passwd文件的每一行的用户名和用户的密码,并用..分隔输出
# vim a.txt
love
love.
loove
looooove
​
# vim file1.txt
isuo
IPADDR=192.168.246.211
hjahj123
GATEWAY=192.168.246.1
NETMASK=255.255.255.0
DNS=114.114.114.114
​
NR   行数。表示记录编号, 在awk将行做为记录, 该变量相当于当前行号,也就是记录号
# awk '{print NR,$0}' a.txt file1.txt
        # 打印出两个文件的每行内容,每一行前面加上行号
1 love
2 love.
3 loove
4 looooove
5  
6 isuo
7 IPADDR=192.168.246.211
8 hjahj123
9 GATEWAY=192.168.246.1
10 NETMASK=255.255.255.0
11 DNS=114.114.114.114

​# cat file1.txt | awk -F: END'{print NR}'  #汇总行数
11

FNR:打印不同文件中的内容,并在每行之前加上该行在各自文件中的行号。
# awk '{print FNR,$0}' a.txt file1.txt
1 love
2 love.
3 loove
4 looooove
5  
1 isuo
2 IPADDR=192.168.246.211
3 hjahj123
4 GATEWAY=192.168.246.1
5 NETMASK=255.255.255.0
6 DNS=114.114.114.114

RS(输入记录分隔符)
1.创建一个文件
# vim passwd  #以每个"bash"作为分隔符,逐行输出到标准输出
root:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologin
# cat passwd | awk 'BEGIN{RS="bash"} {print $0}' 
root:x:0:0:root:/root:/bin/
bin:x:1:1:bin:/bin:/sbin/nologin
​
ORS(输出记录分隔符)
2.对刚才的文件进行修改
# vim passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
# cat passwd | awk 'BEGIN{ORS=" "} {print $0}'
root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin

NF:统计字段的个数
# cat /etc/passwd | awk -F":" '{print NF}'
7
7
7
7
$NF:打印最后一列
# cat /etc/passwd | awk -F":" '{print $NF}'
/bin/bash
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
练习1:将文件合并为一行
[root@awk ~]# cat /etc/passwd | awk 'BEGIN{ORS="" } {print $0}'
练习2:把一行内容分成多行
1.首先创建一个文件
# vim d.txt
root:x:0:0:root:/root:/bin/bash
# cat d.txt | awk 'BEGIN{RS=":"} {print $0}'
root
x
0
0
root
/root

面试:grep、sed、awk的区别 

  • grep: 全局搜索文本。匹配指定模式的行
  • sed: 编辑文本。流编辑器,用于对输入流(标准输入或者文件)执行基本的文本转换
  • awk: 分析文本。根据条件来打印出需要的部分

 关系运算符号

比较表达式

比较表达式采用对文本进行比较,只有当条件为真,才执行指定的动作。比较表达式使用关系
运算符,用于比较数字与字符串。关系运算符有
< 小于 例如 x<y
> 大于 x>y
<= 小于或等于,x<=y
== 等于 x==y
!= 不等于 x!=y
>= 大于等于 x>=y

输出指定用户记录

输出所有使用 /bin/bash 作为默认shell的用户的记录。
# awk -F":" '$NF == "/bin/bash"' /etc/passwd 
输出除了 root 用户之外的所有用户的记录
# awk -F":" '$1 != "root"' /etc/passwd
输出root 用户
# awk -F":" '$3 == 0' /etc/passwd
# 系统用户或服务账号(UID<100)
# awk -F":" '$3 < 100' /etc/passwd

算术运算

+, -, *, /, %(模: 取余), ^(幂:2^3)
可以在模式中执行计算,awk都将按浮点数方式执行算术运算
查找UID大于5的用户记录
# awk -F: '$3 * 10 > 50' /etc/passwd

常见使用

1.打印一个文件中的指定列

# cat /etc/passwd | awk -F : '{print $2,$5}'

2.打印指定行指定列的某个字符

# free -m | awk 'NR==2 {print $2}'

3.统计一个文件的行数

# cat /etc/passwd | awk '{print NR}'

获取根分区的使用量

4.在awk中使用if条件判断

i++===先赋值再运算
++i===先运算再赋值
if语句:
{if(表达式){语句;语句;...}}
​
实战案例:
显示管理员用户姓名
# cat /etc/passwd | awk -F":" '{if($3==0) {print $1 " is administrator"}}'
​
统计系统用户数量
# cat /etc/passwd | awk -F":" '{if($3>=0 && $3<=1000){i++}} END{print i}'

5.在awk中使用for循环

每行打印两遍
# awk '{for(i=1;i<=2;i++) {print $0}}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

统计访问日志的具体信息

1. 统计/etc/passwd中各种类型shell的数量
# cat /etc/passwd | awk -F':' '{print $7}' | sort | uniq -c | sort -n -k1 -r
#提取登录shell的信息,统计每种登录shell的使用次数,并按照次数降序的方式展示统计结果。
参数解释:
uniq:去重
-c:统计连续出现的次数
sort:排序,默认升序
-k:按指定列数排序
-r:降序,即从大到小排序
-n:以数值来排序

nginx默认日志格式

nginx默认自定义日志格式:
log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
access_log  /var/log/nginx/access.log  main;

 2.统计nginx日志出现的状态码
提取HTTP状态码的信息,统计每种状态码出现的次数,以状态码出现次数降序的方式展示
# cat access.log | awk '{print $9}' | sort | uniq -c | sort -n -k 1 -r
​3.统计当前nginx日志中每个ip访问的数量
# cat access.log | awk '{print $1}' | sort | uniq -c | sort -n -k 1 -r
# 读取 access.log 文件。提取每行的第一个字段(客户端 IP 地址)。对 IP 地址进行排序。
统计每个 IP 地址出现的次数,并在前面添加一个计数。按照计数从高到低排序。
​4.统计某一天的nginx日志中的不同ip的访问量
# cat access.log | grep '10/May/2018' | awk '{print $1}' | sort | uniq -c | sort -n -k 1 -r
# 读取 access.log 文件。筛选出包含 '10/May/2018' 字符串的所有行(即只处理那一天的访问记录)。
提取这些行的第一个字段(客户端 IP 地址)。对提取出的 IP 地址进行排序。
统计每个 IP 地址出现的次数,并在前面添加一个计数。按照计数从高到低排序。
5.统计nginx日志中某一天访问最多的前10个ip
# cat access.log | grep '10/May/2018' | awk '{print $1}' | sort | uniq -c | sort -n -k 1 -r | head -n 10
​6.统计tcp连接的状态
# netstat -n | awk '/^tcp/' | awk '{print $NF}' | sort | uniq -c | sort -n -k 1 -r
# 显示所有网络连接状态,并以数字形式显示地址和端口。过滤出 TCP 类型的连接。提取每个连接的状态。
对状态进行排序。统计每个状态出现的次数,并显示每种状态前的计数。按照计数从多到少排序。
LAST_ACK 5 (正在等待处理的请求数)
SYN_RECV 30
ESTABLISHED 1597 (正常数据传输状态)
FIN_WAIT1 51
FIN_WAIT2 504
TIME_WAIT 1057 (处理完毕,等待超时结束的请求数)

UV与PV统计

PV:即访问量,也就是访问您商铺的次数;
例如:今天显示有300 PV,则证明今天你的商铺被访问了300次。
UV:即访问人数,也就是有多少人来过您的商铺;  #需要去重
例如:今天显示有50 UV,则证明今天有50个人来过你的商铺。
=================================================================
1.根据访问IP统计UV
# cat access.log | awk '{print $1}' |sort |uniq | wc -l
# 显示 access.log 文件的内容。提取每一行的第一个字段(客户端 IP 地址)。
对提取的 IP 地址进行排序。筛选出唯一的 IP 地址。统计这些唯一 IP 地址的数量。
2.根据访问ip统计PV
# cat access.log | awk '{print $1}' |wc -l
或者是url
# cat access.log | awk '{print $7}' |wc -l
3.查询访问最频繁的URL
# cat access.log | awk '{print $7}'|sort | uniq -c |sort -n -k 1 -r | less
# 显示 access.log 文件的内容。抽取每一行的第7个字段(请求 URL)。对抽取的 URL 进行排序。
统计每个唯一 URL 的出现次数。按照出现次数降序排列。使用 less 命令分页显示结果。
4.查询访问最频繁的IP
# cat access.log | awk '{print $1}'|sort | uniq -c |sort -n -k 1 -r | less

练习:切割nginx的日志,统计PV\UV,出现次数最多的url等各种切割统计

#!/bin/bash
# 定义日志文件路径
LOG_FILE="/var/log/nginx/access.log"

# 1. 显示 PV (页面浏览量)
display_pv() {
    # 使用 awk 提取每行的 URL 字段,并计算总数
    pv=$(awk '{print $7}' "$LOG_FILE" | wc -l)
    echo "页面浏览量 (PV): $pv"
}

# 2. 显示 UV (独立访客数)
display_uv() {
    # 使用 awk 提取每行的 IP 地址字段,并计算去重后的数量
    uv=$(awk '{print $1}' "$LOG_FILE" | sort | uniq | wc -l)
    echo "独立访客数 (UV): $uv"
}

# 3. 显示出现次数最多的 URL
display_top_url() {
    # 使用 awk 提取每行的 URL 字段,并统计出现次数
    top_url=$(awk '{print $7}' "$LOG_FILE" | sort | uniq -c | sort -nr | head -n 1)
    echo "出现次数最多的 URL: $top_url"
}

# 主菜单
menu() {
    echo "请选择一个选项:"
    echo "1. 显示 PV (页面浏览量)"
    echo "2. 显示 UV (独立访客数)"
    echo "3. 显示出现次数最多的 URL"
    echo "4. 退出程序"
    read -p "请输入菜单编号: " choice

    case $choice in
        1)
            display_pv
            ;;
        2)
            display_uv
            ;;
        3)
            display_top_url
            ;;
        4)
            exit 0
            ;;
        *)
            echo "无效的选择,请重新输入!"
            menu
            ;;
    esac

    menu
}

# 检查日志文件是否存在
if [ ! -f "$LOG_FILE" ]; then
    echo "日志文件 '$LOG_FILE' 不存在,请检查路径是否正确。"
    exit 1
fi

# 启动主菜单
menu

Expect自动交互工具

在实际工作中运行命令、脚本或程序时, 需要手动从终端输入某些继续运行的指令。expect 根据程序的提示, 模拟标准输入提供给程序, 实现自动化交互执行。 作为一个免费的编程工具, expect实现自动的交互式任务,而无需人为干预,说白了 expect 就是一套用来实现自动交互功能的软件。

通过expect实现将交互式的命令变为非交互式执行,不需要人为干预(手动输入)。

expect安装

# yum -y install expect
expect语法
用法: 
1)定义expect脚本执行的shell
        #!/usr/bin/expect     -----类似于#!/bin/bash 
2)spawn
        spawn是执行expect之后后执行的内部命令开启一个会话 #功能:用来执行shell的交互命令
3)expect ---相当于捕捉
        功能:判断输出结果是否包含某项字符串(相当于捕捉命令的返回的提示)。没有捕捉到则会断开,否则等待一段时间后返回,等待通过timeout设置 
4)send
        执行交互动作,将交互要执行的命令进行发送给交互指令,命令字符串结尾要加上“\r”,#---相当于回车
5)interact 
        执行完后保持交互状态,需要等待手动退出交互状态,如果不加这一项,交互完成会自动退出
6)exp_continue 
        继续执行接下来的操作
7)timeout
        返回设置超时时间(秒)

非交互式ssh连接

(1)普通操作

# vim expect01.sh
#!/usr/bin/expect
spawn ssh root@192.168.246.115
​
expect {
        "yes/no" {  send "yes\r"; exp_continue }#\r表示回车
        "password:" { send "1\r" };
}
interact
# chmod +x expect01.sh
# ./expect01.sh
spawn ssh root@192.168.246.115
root@192.168.246.115's password: 
Last login: Fri Aug 28 16:57:09 2019
​
#如果添加interact参数将会等待我们手动交互进行退出。如果不加interact参数在登录成功之后会立刻退出。
expect eof  #也是直接退出expect模式

(2)自动化 SSH 登录过程(设置变量与传参)

注意:expect环境中设置变量用set,识别不了bash方式定义的变量 。

#!/usr/bin/expect

# 设置变量
set user root          # 设置用户名
set pass 1             # 设置密码
set ip [lindex $argv 0] # 从命令行参数中获取 IP 地址
set timeout 10         # 设置超时时间为 10 秒

# 启动 SSH 会话
spawn ssh $user@$ip

# 等待并处理可能出现的不同情况
expect {
    "yes/no" {  # 如果出现 "Are you sure you want to continue connecting (yes/no)?" 的提示
        send "yes\r"     # 发送 "yes" 和回车键
        exp_continue     # 继续等待下一个模式
    }
    "password:" {        # 如果出现 "password:" 的提示
        send "$pass\r"   # 发送密码和回车键
    }
}

# 进入交互模式,允许用户与 SSH 会话直接交互
interact
# chmod +x expect01.sh  # 使脚本可执行
# ./expect01.sh 192.168.246.115  # 运行脚本并传入 IP 地址
spawn ssh root@192.168.246.115
root@192.168.246.115's password: 
Last login: Fri Aug 28 07:13:57 2019 from 192.168.246.135

 (3)批量推送公钥实现免密连接

ping通一个ip地址连接一个ip
# vim getip_push.sh
#!/usr/bin/bash
#判断expect命令是否安装
rpm -qa expect &> /dev/null
if [ $? -ne 0 ];then
        yum install -y expect
        if [ $? -eq 0 ];then
            echo "expect安装成功"
        fi
fi
​
#判断主机下面是否生成秘钥,如果没有生成秘钥
if [ ! -f ~/.ssh/id_rsa ];then
        ssh-keygen -t rsa -P "" -f ~/.ssh/id_rsa
        if [ $? -ne 0];then
            echo "密钥文件生成失败"
        fi
fi
​
#循环执行获取up状态的ip地址。
for i in {2..254}
do
        {
        ip=192.168.198.$i
        ping -c1 $ip &> /dev/null
        if [ $? -eq 0 ];then
                echo "$ip" >> up_ip.txt
                set timeout 10
                /usr/bin/expect <<-EOF   #shell脚本中调用expect命令
                spawn ssh-copy-id $ip
                expect {
                        "yes/no" { send "yes\r"; exp_continue }
                        "password:" { send "1\r" };
                }
                expect eof
                EOF
        fi      
        } &
wait
done
echo "finish..."
​
# chmod +x getip_push.sh 
# ./getip_push.sh
​
测试....

练习

shell 编程-运维脚本实战

• 实战项目1: 实现网络配置
• 实战项目2: sed实现sshd配置修改端口
sed -ir.bak "s/^#*Port.*/Port $new_port/" /etc/ssh/sshd_config
• 实战项目3: sed实现nginx配置修改端口为8080
sed -ir 's/listen\s+80;/listen 8080;/g' /etc/nginx/nginx.conf
sed -ir 's/listen\s+\[\:\:\]\:80;/listen [::]:8080;/g' /etc/nginx/nginx.conf
• 实战项目4: sed实现关闭本机SELinux的功能(/etc/sysconfig/selinux)
sed -ir 's/^SELINUX=.*/SELINUX=disabled/' etc/sysconfig/selinux
• 实战项目5: awk统计/etc/passwd各种shell数量
awk -F: '{print $7}' /etc/passwd |sort|uniq -c|sort -n -k1 
• 实战项目6: awk统计网站访问各种状态数量
cat access.log | awk '{print $9}' | sort | uniq -c | sort -n -k 1 -r
• 实战项目7: awk统计访问的每个IP的数量
cat access.log | awk '{print $1}' | sort | uniq -c | sort -n -k 1 -r
• 实战项目8: 统计Nginx日志中某一天的PV量
cat access.log | awk '{print $1}' |wc -l
• 实战项目9: 获取获得内存使用情况
• 实战项目10: 基于时间的备份脚本
• 实战项目11: Web日志访问量分析程序(PV、UV)
• 实战项目12: 编写系统初始化脚本
        1)设置时区并把同步时间加入计划任务
ntpdate pool.ntp.org
timedatectl set-timezone Asia/Shanghai
(crontab -l ; echo "0 1 * * * /usr/sbin/ntpdate pool.ntp.org") | crontab -
        2)禁用selinux
        3)历史命令显示操作时间 
        4)安装常用工具
• 实战项目13: Linux系统状态收集及分析(内存使用量,硬盘使用量,cpu使用量等)
free -h    #内存使用量
df -h     #硬盘使用量
yum install -y sysstat  
mpstat 1 1 | awk '/Average:/ { print $11, $12 }' #平均空闲和平均忙碌的CPU百分比

练习

系统初始化
1.检查网络:1.使用dhcp 2.设置静态ip
2.关闭防火墙和selinux
3.替换yum源
4.安装必要的工具(vim/wget/ntpdate/lrzsz/unzip/net-tools)
5.设置时间同步
【6.磁盘分区---给新买磁盘做分区】
7.更新DNS
8.修改ssh会话保持
9.限制用户登录次数锁死时间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值