Shell编程学习笔记05

2024-01-08 03:47:02

第五章、三剑客

正则表达式

前言

名词解释:正则表达式(regular expression,RE)是一种字符模式,用于在查找过程中匹配指定的字符。在大多数程序里,正则表达式都被置于两个正斜杠之间;例如/l[oO]ve/就是由正斜杠界定的正则表达式,它将匹配被查找的行中任何位置出现的相同模 式。在正则表达式中,元字符是最重要的概念。

工具:被vim、sed、awk、grep调用

场景:mysql、oracle、php、python,Apache,Nginx...需要正则

回顾:

需求:匹配数字的脚本:用户输入创建账号的数量

语法:[[ ^[0-9]+$ ]]

示范:

read -p "输入数字才退出:" num

while :

do

if [[ ! $num =~ ^[0-9]+$ ]];then

echo "error enter!"

read -p "输入数字才退出:" num

else

echo "thank you"

exit 1

fi

done

元字符

定义:元字符是这样一类字符,它们表达的是不同于字面本身的含义

分类

基本正则表达式元字符

^:行首定位符

[root@localhost ~]# grep "root" /etc/passwd

root:x:0:0:root:/root:/bin/bash

operator:x:11:0:operator:/root:/sbin/nologin

[root@localhost ~]#grep "^root" /etc/passwd

root:x:0:0:root:/root:/bin/bash

$:行尾定位符

love$

.:匹配任意单个字符

[root@localhost ~]# grep abc 1.txt

abc

[root@localhost ~]# grep adc 1.txt

adc

[root@localhost ~]# grep a.c 1.txt

abc

adc

*:匹配前导符(字符、子表达式或字符类)0次到多次出现

[root@localhost ~]# cat 1.txt

a

ab

abc

abcd

abcde

abcdef

ggg

hhh

[root@localhost ~]# grep "abc*" 1.txt

ab

abc

abcd

abcde

abcdef

[root@localhost~]# grep "abcd*" 1.txt

abc

abcd

abcde

abcdef

.*:匹配任意多个字符

[root@localhost ~]# grep ".*" 1.txt

a

ab

abc

abcd

abcde

abcdef

ggg

hhh

iii

[ ]:匹配指定范围内的一个字符? ? [IL]ove

[root@localhost ~]# cat 1.txt

love

Love

1ove

iove

[root@localhost ~]#grep [IL]ove 1.txt

love

Love

[-]:匹配指定范围内的一个字符,连续的范围

[A]:匹配不在指定组内的字符

\:用来转义元字符(' ' " " \),脱意符

\<:词首定位符

[root@localhost ~]# grep "love" 1.txt

love

iloveyou

[root@localhost ~]# grep "\love" 1.txt

love

\>:词尾定位符? ? love\>

():\(..\) 匹配稍后使用的字符的标签

:3,9 s/\(.*\)/#\1 /加注释

x\{m\}: 字符x重复出现m次

[root@localhost ~]# grep o 1.txt

love

loove

looove

[root@localhost ~]# grep "o\(3\)" 1.txt

looove

x\{m,\}:字符x重复出现m次以上 o\{5,\}

x\m,n\}:字符x重复出现m到n次 o\{5,10\}

扩展正则表达式元字符

+:匹配1~n个前导字符

[root@localhost ~]# cat 1.txt

Ive

love

loove

[root@localhost ~]#egrep lo+ve 1.txt

love

loove

?:匹配0~1个前导字符? ? lo?ve:?前面的无论是否有o都可以

[root@localhost ~]# egrep lo?ve tom.sh

love

Ive

a|b:匹配a或b

[root@localhost ~]# egrep "o|v" 1.txt

lve

love

loove

looove

():组字符

[root@localhost ~]# egrep "loveable | rs"1.txt

rs

loveable

lovers

[root@localhost~]# egrep "love(able|rs)" 1.txt

loveable

lovers

示例

grep love 1.txt

/^love/:匹配以"love"开头的字段。

/love$/:匹配以"love"结尾的字段。

/l.ve/:匹配包含"l"、任意字符、"ve"的字段。

/lo*ve/:匹配包含"l"、零个或多个"o"、"ve"的字段。

/[Ll]ove/:匹配"Love"或"love"。

/love[a-z]/:匹配"love"后面跟着任意一个小写字母的字段。

/love[^a-zA-Z0-9]/:匹配"love"后面跟着任意一个非字母和非数字字符的字段。

/.*/:匹配任意字符。

/^$/:匹配空字段。

/^[A-Z]..$/:匹配以大写字母开头,后面跟着任意两个字符的字段。

/^[A-Z][a-z ]*3[0-5]/:匹配以大写字母开头,后面跟着零个或多个小写字母或空格,以及以"3"后面跟着0到5之间的数字结尾的字段。

/[a-z]*\./:匹配零个或多个小写字母后面跟着一个句点的字段。

/^ *[A-Z][a-z][a-z]$/:匹配以零个或多个空格开头,后面跟着一个大写字母,最后是两个小写字母的字段。

/^[A-Za-z]*[^,][A-Za-z]*$/:匹配以零个或多个字母开头,后面跟着一个非逗号字符,最后是零个或多个字母的字段。

/\<fourth\>/:匹配单词"fourth"。

/\<f.*th>/:匹配以"f"开头,后面跟着任意个字符,最后是"th"的字段。

/5{2}2{3}\./:匹配"55222"后面跟着一个句点的字段。

/^[ \t]*$/:匹配以零个或多个空格或制表符开头并且没有其他字符的字段。

/^#/:匹配以"#"开头的字段。

/^[ \t]*#/:匹配以零个或多个空格或制表符开头,后面跟着一个"#"的字段。

:1,$ s/\([Oo]ccur\)ence/\1rence/:将"Occurence"或"occurence"替换为"Occurrence"或"occurrence"。

:1,$ s/\(square\) and \(fair\)/\2 and \1/:将"square and fair"替换为"fair and square"。

grep

目的:过滤,查找文档中的内容

分类:

grep

egrep 扩展支持正则

\w 所有字母与数字,称为字符 [a-zA-Z0-9] 'l[a-zA-Z0-9]*ve' === '|\w*ve'

\W 所有字母与数字之外的字符,称为非字符 'love[^a-zA-Z0-9]+' === 'love\W+'

\b 词边界 '\' === '\blove\b'

fgrep 不支持正则

[root@localhost ~]# fgrep.1.txt

I.ve

返回值

  • 0是找到了 表示成功;
  • 1是没有找到
  • 2是找到地方不对

示范:

## grep 'root' /etc/passwd

root:x:0:0:root:/root:/bin/bash

operator:x:11:0:operator:/root:/sbin/nologin

## echo $?

0

## grep 'root1' /etc/passwd #用户root1并不存在

## echo $?

1

## grep 'root' /etc/passwd1 #这里的/etc/passwd1文件并不存在

grep:/etc/passwd1: No such file ordirectory

## echo $?

2

参数

grep -q:静默模式,用于在命令行中查找匹配的文本,但不显示匹配结果。它通常用于脚本中,只关心匹配与否,而不需要显示具体匹配内容。

grep -v:反向匹配模式,用于在命令行中查找不匹配的文本。它会显示不包含指定模式的行。

grep -R:递归搜索模式,用于在指定目录及其子目录下搜索匹配的文本。它会搜索目录中的所有文件,并显示包含匹配模式的行。

grep -o:只显示匹配的部分,而不显示整行。它会提取出匹配模式的部分,并将其显示出来。

grep -B2:显示匹配行及其前两行。它会显示包含匹配模式的行,并显示前两行作为上下文。

grep -A2:显示匹配行及其后两行。它会显示包含匹配模式的行,并显示后两行作为上下文。

grep -C2:显示匹配行及其前后两行。它会显示包含匹配模式的行,并显示前后两行作为上下文。

egrep -l:只显示匹配模式的文件名,而不显示具体匹配内容。它用于在多个文件中查找匹配模式,并只显示包含匹配模式的文件名。

egrep -n:显示匹配行及其行号。它会显示包含匹配模式的行,并在每行前面显示行号。

示例

grep -E或egrep 进行使用

# egrep 'NW' datafile.txt:在"datafile.txt"中查找包含"NW"的行。

# egrep 'NW' d*.txt:在以"d"开头的txt文件中查找包含"NW"的行。

# egrep '^n' datafile.txt:在"datafile.txt"中查找以"n"开头的行。

# egrep '4$' datafile.txt:在"datafile.txt"中查找以"4"结尾的行。

# egrep TB Savage datafile.txt:在"datafile.txt与Savage"中查找包含"TB "的行。

# egrep 'TB Savage' datafile.txt:在"datafile.txt"中查找包含"TB Savage"的行。

# egrep '5\..' datafile.txt:在"datafile.txt"中查找以"5"开头,后跟一个点和任意字符的行。

# egrep \.5' datafile.txt:在"datafile.txt"中查找包含".5"的行。

# egrep '^[we]' datafile.txt:在"datafile.txt"中查找以"we"开头的行。

# egrep '[^0-9]' datafile:在"datafile.txt"中查找不包含数字的字符。

# egrep '[A-Z][A-Z] [A-Z]' datafile:在"datafile.txt"中查找包含三个大写字母的行。

# egrep 'ss* ' datafile:在"datafile.txt"中查找包含"s"后跟零个或多个s的行。

# egrep '[a-z]{9}' datafile:?在"datafile.txt"中查找出现了九次小写字母的行。

# egrep "^north" 在"datafile.txt"中查找以"north"开头的行。

# egrep '\<north>' datafile:在"datafile.txt"中查找单词"north"。

# egrep '\<[a-r].*n\>' datafile:在"datafile.txt"中查找以字母"a"到"r"开头,后跟零个或多个字符,最后以"n"结尾的单词。

# egrep '^n\w*\W' datafile:在 "datafile" 文件中查找以字母 "n" 开头,后跟零个或多个字母、数字或下划线字符,最后以一个非字母、数字或下划线字符结尾的单词

# egrep '\bnorth\b' datafile:在"datafile.txt"中查找单词"north"。

# egrep 'NW | EA' datafile:在"datafile.txt"中查找包含"NW"或"EA"的行。

# egrep '3+' datafile:在"datafile.txt"中查找包含一个或多个"3"的行。

# egrep '2\.?[0-9]' datafile:在"datafile.txt"中查找以"2"开头,后跟零个或一个点,再后跟一个数字的行。

# egrep '(no)+' datafile:在"datafile.txt"中查找包含一个或多个"no"的行。

# egrep 'S(h|u)' datafile:在"datafile.txt"中查找包含"Sh"或"Su"的行。

# egrep 'Sh|u' datafile\:在"datafile.txt"中查找包含"Sh"或"u"的行。

sed

前言

Stream EDitor:流编辑

sed是一种在线的、非交互式的编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”( patternspace),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。

接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。Sed主要用来自动编辑 个或多个文件;简化对文件的反复操作;

格式

1 sed 选项 命令 文件

sed [options] 'command' file(s)

2 sed 选项 -f 脚本 文件

sed [options] -f scriptfile file(s)

返回值

都是0,对错不管。

只有当命令存在语法错误时,sed的退出状态才是非0

sed和正则表达式

与grep一样,sed在文件中查找模式时也可以使用正则表达式(RE)和各种元字符。

正则表达式是括在斜杠间的模式,用于查找和替换,以下是sed支持的元字符。

使用基本元字符集 ^,$,.,*,[],[^], \,\(\),\{\}

使用扩展元字符集 ?,+,|,()

使用扩展元字符的方式:

\+ 转义

sed -r 加-r用于启用扩展正则表达式语法

汇总示例

删除命令: d

# sed -r '/root/d' passwd

在名为?passwd?的文件中删除包含关键字 "root" 的行。

# sed -r '3d' passwd

在名为?passwd?的文件中删除第三行。

# sed -r '3{d}' passwd

在名为?passwd?的文件中删除第三行。这里使用了花括号?{}?来指定要执行的命令,即删除行。

# sed -r '3{d;}' passwd

在名为?passwd?的文件中删除第三行。与上一个命令相比,这里使用了分号?;?来分隔多个命令。d?表示删除行。

# sed -r '3,$d' passwd

在名为?passwd?的文件中删除从第三行到最后一行的内容。3,$?表示从第三行到最后一行的范围。

# sed -r '$d' passwd

在名为?passwd?的文件中删除最后一行。

替换命令:s

# sed -r 's/root/aofa/' passwd

在名为?passwd?的文件中将第一个匹配到的 "root" 替换为 "aofa"。

# sed -r 's/^root/aofa/' passwd

在名为?passwd?的文件中将以 "root" 开头的行替换为以 "aofa" 开头的行。

# sed -r 's/root/aofa/g' passwd

在名为?passwd?的文件中将所有匹配到的 "root" 替换为 "aofa"。g?表示全局替换,即替换所有匹配项。

# sed -r 's/[0-9][0-9]$/&.5/' passwd

在名为?passwd?的文件中将以两个数字结尾的行,在行尾添加 ".5"。[0-9][0-9]$?表示匹配以两个数字结尾的模式,&?表示匹配到的内容本身。

# sed -r 's/(mail)/E\1/g' passwd

在名为?passwd?的文件中将所有匹配到的 "mail" 替换为 "Email"。(mail)?使用括号捕获 "mail",\1?表示捕获组的引用。

# sed -r 's#(mail)#E\1#g' passwd

在名为?passwd?的文件中将所有匹配到的 "mail" 替换为 "Email"。(mail)?使用括号捕获 "mail",\1?表示捕获组的引用。这里使用?#?作为替换命令的分隔符,以避免与斜杠冲突。

读文件命令:r

# sed -r '$r 1.txt' passwd

在名为?passwd?的文件的末尾追加来自?1.txt?文件的内容。$?表示最后一行,r?表示读取文件并将其内容追加到当前行之后。

# sed -r '/root/r 1.txt' passwd

在名为?passwd?的文件中,对于包含关键字 "root" 的行,在该行之后追加来自?1.txt?文件的内容。/root/?是一个模式,r?表示读取文件并将其内容追加到匹配行之后。

VI中也有类似命令

(#vim 1.txt

111111111

2222222

3333333333

aaaaaa

bbbbbb

CCCCCC

:$ r a.txt)

在当前文件中,读取其他文件“部分”内容。

写文件命令:W(另存为)

# sed -r 'w 111.txt' 1.txt

将名为?1.txt?的文件的内容写入到名为?111.txt?的文件中。w?表示写入操作。

# sed -r '/root/w 123.txt' passwd

将名为?passwd?的文件中包含关键字 "root" 的行写入到名为?123.txt?的文件中。/root/?是一个模式,w?表示写入操作。

# sed -r '1,5w 123.txt' passwd

将名为?passwd?的文件的第1行到第5行的内容写入到名为?123.txt?的文件中。1,5?表示行的范围,w?表示写入操作。

追加命令:a(之后)

# sed -r 'a123' passwd

在名为?passwd?的文件中的每一行后面添加字符串 "123"。a?表示追加操作。

# sed -r '2a123' passwd

在名为?passwd?的文件的第二行后面添加字符串 "123"。2?表示第二行,a?表示追加操作。

# sed -r '2a 1111\

> 3333333\

> 444444' passwd

在名为 passwd 的文件的第二行后面添加多行文本。\用于换行,a?表示追加操作。

插入命令:i(之前)

# sed -r '2iaaaaaaaa' passwd

在名为?passwd?的文件的第二行之前插入字符串 "aaaaaaaa"。2?表示第二行,i?表示插入操作。

# sed -r '2i 123\

>456\

> 789' passwd

在名为 passwd 的文件的第二行之前插入多行文本。\用于换行,i?表示插入操作。

替换整行命令:c

# sed -r '2caaaaaaaa' passwd

将名为?passwd?的文件的第二行替换为字符串 "aaaaaaaa"。

获取下一行命令:n

# sed -r '/root/{n;d}' passwd

在名为?passwd?的文件中,对于包含关键字 "root" 的行,删除包含关键字 "root" 的行的下一行。

# sed -r /root/{n;s/bin/ding/g}' passwd

在名为?passwd?的文件中,对于包含关键字 "root" 的行,将其下一行中的 "bin" 替换为 "ding"

反向选择:!

# sed -r '2,$d' passwd

删除名为?passwd?的文件中从第二行到最后一行的内容。

# sed -r '2,$!d' passwd

删除名为?passwd?的文件中除了第二行到最后一行之外的所有行。

多重编辑:e

# sed -r -e '1,3d' -e '4s/adm/admin/g' passwd

它使用了两个?-e?选项来指定多个表达式。第一个表达式?1,3d?表示删除名为?passwd?的文件中的第一行到第三行。第二个表达式?4s/adm/admin/g?表示在第四行中将所有的 "adm" 替换为 "admin"。

# sed -r '1,3d;4s/adm/admin/g' passwd

它使用了分号?;?来分隔多个表达式。第一个表达式?1,3d?表示删除名为?passwd?的文件中的第一行到第三行。第二个表达式?4s/adm/admin/g?表示在第四行中将所有的 "adm" 替换为 "admin"。

# sed -r '2s/bin/ding/g;2s/nologin/bash/" passwd

使用了分号?;?来分隔多个表达式。第一个表达式?2s/bin/ding/g?表示在第二行中将所有的 "bin" 替换为 "ding"。第二个表达式?2s/nologin/bash/?表示在第二行中将 "nologin" 替换为 "bash"。

# sed -r '2{s/bin/ding/g;s/nologin/bash/}' passwd

它使用了花括号?{}?来指定要在第二行上执行的多个表达式。第一个表式?s/bin/ding/g?表示在第二行中将所有的 "bin" 替换为 "ding"。第二个表达式?s/nologin/bash/?表示在第行中将 "nologin" 替换为 "bash"。

实战案例

删除配置文件中#号注释行

# sed -r /^#/d' /etc/vsftpd/vsftpd.conf

修改文件:

# sed -ri '$a\chroot_local_user=YES' /etc/vsftpd/vsftpd.conf

在/etc/vsftpd/vsftpd.conf文件的末尾添加一行内容chroot_local_user=YES。-i选项用于直接修改原始文件。

# sed -ri '/SELINUX=/cSELINUX=disabled' /etc/selinux/config

将/etc/selinux/config文件中包含SELINUX=的行替换为SELINUX=disabled。/c命令用于替换匹配的行。

给文件行添加注释:

# sed -r '2,6s/^/#/' a.txt

# sed -r '2,6s/(.*)/#\1/'a.txt

((.*):这是一个捕获组,用括号()括起来。它表示匹配任意数量的任意字符,并将其捕获到该组中。捕获组允许我们在替换中引用这个匹配的内容。/#\1/:这是替换字符串,其中/#表示要添加到替换结果中的#字符,而\1表示对第一个捕获组的引用。

当使用s/.../.../替换命令时,\1用于引用第一个捕获组的内容。在这种情况下,/#\1/表示将#字符添加到第一个捕获组的内容之前。)

# sed -r '2,6s/.*/#&/' a.txt

(当使用s/.../.../替换命令时,&用于引用与模式匹配的内容。在这种情况下,#&表示将

#字符添加到模式匹配的整个字符串之前。)

sed中使用外部变量

准备工作:# var1=11111

追加变量:# sed -r "1a$var1" /etc/hosts

注意调用变量时,使用单引号是错误的

巧合:

# sed -r "$a$var1" /etc/hosts

报错了,$a最后一行追加被误认为变量了。

# sed -r "\$a$var1"/etc/hosts

(\$a:这是一个sed命令,用于在文件的最后一行追加内容。在这里,\$表示匹配行尾,a表示追加操作。

$var1:这是一个变量,它的值将被追加到文件的最后一行。)

awk

一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。

基本用法

awk [选项参数] '/patternl/{action1} /pattern2/{action2}...' filename

pattern:表示awk在数据中查找的内容,就是匹配模式

action:在找到匹配内容时所执行的一系列命令

选项参数说明

选项参数? ? ? ? 功能

-F? ? ? ? ?指定输入文件分隔符

-v? ? ? ? ?赋值一个用户定义变量

案例实操

(1)数据准备

[atguigu@hadoop101 shells]$ sudo cp /etc/pasawd ./ (将/etc/pasawd文件复制到当前目录下。)

passwd数据的含义:

用户名:密码(加密过后的):用户id:组id:注释:用户家目录:shell解析器

(2)搜索passwd文件以root关键字开头的所有行,并输出该行的第7列。

[atguigu@hadoop101 shells]$ awk -F :'/^root/{print $7}' pasawd

/bin/bash

(3)搜索passwd文件以root关键字开头的所有行,并输出该行的第1列和第7列,中间以“,”号分割。

[atguigu@hadoop101 shells]$ awk -F : '/^root/{print $1","$7}' passwd

root,/bin/bash

注意:只有匹配了pattem的行才会执行 action。

(4)只显示/etc/passwd的第一列和第七列,以逗号分割,且在所有行前面添加列名user,shell在最后一行添加"dahaige,/bin/zuishuai"。

[atguigu@hadoop101shells]$ awk -F : 'BEGIN{print "user,shell"} {print $1","$7} END{print "dahaige,/bin/zuishuai"} passwd

user,shelle

root,/bin/bashd

bin,/sbin/nologind

。。。

atguigu,/bin/bashd

dahaige,/bin/zuishuai

注意:BEGIN在所以数据读取行之前执行;END在所以数据执行之后执行。

(5)将passwd文件中的用户id增加数值1并输出

[atguigu@hadoop101shells]$ awk-v i=1 -F :{print $3+i}' passwd

1

2

3

4

awk的内置变量

变量? ? ? ? ? ? ? ? ? ? ? ?说明

FILENAME? ? ? ? ? 文件名

NR? ? ? ? ? ? ? ?已读的记录数(行号)

NFI? ? 浏览记录的域的个数(切割后,列的个数)

案例实操

(1)统计passwd文件名,每行的行号,每行的列数

[atguigu@hadoop101 shells]$ awk -F : '{print "filename:" FILENAME ",linenum:" NR ",col:" NF}' passwd

filename:passwd,linenum:1,col:7

filename:passwd,linenum:2,col:7

filename:passwd,linenum:3,col:7

...

(2)查询ifconfig命令输出结果中的空行所在的行号

[atguigu@hadoop101 shells]$ ifconfig | awk '/^$/{print NR}'

9

18

26

(3)切割IP

[atguigu@hadoop101 shells]$ ifconfig ens33 | awk '/netmask/ {print $2}'

192.168.6.101

cut

cut 的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出。

基本用法

cut [选项参数] filename

说明:默认分隔符是制表符

选项参数说明

选项参数? ? ? ? ? ? ? ? ? ? ? ? ?功能

-f? ? ? ? ? ? ? ? ? ? ? ? 列号,提取第几列

-d? ?分隔符,按照指定分隔符分割列,默认是制表符“\t”

-c? ? ? 按字符进行切割 后面加n 表示取第几列 比如 -c 1

案例实操

数据准备

[atguigu@hadoop101 shells]$ touch cut.txte

[atquiqu@hadoop101 shells]$ vim cut.txt

dong shen

guan zhen

wo wo

lai lai

le le

切割cut.txt第一列

[atguigu@hadoop101 shells]$ cut -d " " -f 1 cut.txt

dong

guan

wo

lai

le

切割cut.txt第二、三列

[atguigu@hadoop101 shells]$ cut -d " " -f 2,3 cut.txt

shen

wo

zhen

lai

le

在cut.txt文件中切割出 guan

[atguigu@hadoop101 shells]$ cat cut.txt | grep guan cut -d " " -f 1

guan

选取系统PATH变量值,第2个冒号开始后的所有路径:

[atguigu@hadoop101 shells]$ echo $PATH

/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/atguigu/.local/bin:/ home/atguiqu/bin

[atguigu@hadoop101 shells]$ echo $PATH cut -d ":"-f 3-

/usr/local/sbin:/usr/sbin:/home/atguigu/.local/bin:/home/atguigu/bin

切割ifconfig 后打印的IP地址

[atguigu@hadoop101 shells]$ ifconfig ens33 | grep netmask cut -d " " -f 10

192.168.111.101

文章来源:https://blog.csdn.net/sjdhdbjd/article/details/135370890
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。