shell-6 case 函数 正则


https://www.bilibili.com/video/BV1st411N7WS/?p=144&spm_id_from=pageDriver&vd_source=867fa98b57c5df7e6cb7e8f3ad59fd84

一、case语句

1.语法结构

说明:pattern表示需要匹配的模式


case var in             定义变量;var代表是变量名
pattern 1)              模式1;用 | 分割多个模式,相当于or
    command1            需要执行的语句
    ;;                  两个分号代表命令结束
pattern 2)
    command2
    ;;
pattern 3)
    command3
    ;;
		  *)              default,不满足以上模式,默认执行*)下面的语句
    command4
    ;;
esac							esac表示case语句结束

2. 应用案例

㈠ 脚本传不同值做不同事

**具体需求:**当给程序传入start、stop、restart三个不同参数时分别执行相应命令

#!/bin/env bash
case $1 in
        start|S)
        service apache start &>/dev/null && echo "apache 启动成功"
        ;;
        stop|T)
        service apache stop &>/dev/null && echo "apache 停止成功"
        ;;
        restart|R)
        service apache restart &>/dev/null && echo "apache 重启完毕"
        ;;
        *)
        echo "请输入要做的事情..."
        ;;
esac

㈡ 根据用户需求选择做事

具体需求:

脚本提示让用户输入需要管理的服务名,然后提示用户需要对服务做什么操作,如启动,关闭等操作

#!/bin/env bash
read -p "请输入你要管理的服务名称(vsftpd):" service
case $service in
        vsftpd|ftp)
        read -p "请选择你需要做的事情(restart|stop):" action
        case $action in
                stop|S)
                service vsftpd stop &>/dev/null && echo "该$serivce服务已经停止成功"
                ;;
                start)
                service vsftpd start &>/dev/null && echo "该$serivce服务已经成功启动"
                ;;
        esac
        ;;
        httpd|apache)
        echo "apache hello world"
        ;;
        *)
        echo "请输入你要管理的服务名称(vsftpd)"
        ;;
esac
	

㈢ 菜单提示让用户选择需要做的事

具体需求:

模拟一个多任务维护界面;当执行程序时先显示总菜单,然后进行选择后做相应维护监控操作

我们首先来学下cat,cat 显示的内容可以来源于文件,也可以来源于标准输入,例如如下,输入aa,打印aa,输入bb,打印bb

[root@node2 shell105]# cat   --直接回车
aa
aa
bb
bb
cc
cc  
最后按下ctrl+d 退出
[root@node2 shell105]# cat <<END
> A
> B
> END
A
B
[root@node2 shell105]# cat <<END &>/dev/null
> a
> bc
> END
不打印输出

例如切换到yunwei用户,并且执行hostname 和id命令

[root@node2 shell105]# su - yunwei <<EOF
hostname
id
> EOF
上一次登录:二 1025 18:03:05 CST 2022
node2
uid=1020(yunwei) gid=1021(yunwei) groups=1021(yunwei) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

vim 编辑打开以后,可以:set list 打开制表符

#!/bin/env bash
#打印菜单
cat <<EOF
  h 显示命令帮助
  f 显示磁盘分区
  d 显示磁盘挂载
  m 显示内存使用
  u 查看系统负载
  q 退出程序
EOF

#让用户输入需要的操作

while true
do
  read -p "请输入需要操作的选项[f|d]:" var
  case $var in
    h)
       cat <<-EOF
           h 显示命令帮助
           f 显示磁盘分区
           d 显示磁盘挂载
           m 显示内存使用
           u 查看系统负载
           q 退出程序
EOF
    ;;
    f)
      fdisk -l
    ;;
    d)
      df -h
    ;;
    m)
      free -m 
    ;;
    u)
    uptime
    ;;
    q)
      exit
    ;;
  esac    
done

进一步优化

#!/bin/bash
#打印菜单
menu(){
cat <<-END
	h	显示命令帮助
	f	显示磁盘分区
	d	显示磁盘挂载
	m	查看内存使用
	u	查看系统负载
	q	退出程序
	END
}
menu
while true
do
read -p "请输入你的操作[h for help]:" var1
case $var1 in
	h)
	menu
	;;
	f)
	read -p "请输入你要查看的设备名字[/dev/sdb]:" var2
	case $var2 in
		/dev/sda)
		fdisk -l /dev/sda
		;;
		/dev/sdb)
		fdisk -l /dev/sdb
		;;
	esac
	;;
	d)
	lsblk
	;;
	m)
	free -m
	;;
	u)
	uptime
	;;
	q)
	exit
	;;
esac
done

二、函数

1. 函数定义

函数名()
{
  函数体(一堆命令的集合,来实现某个功能)   
}

或者

function 函数名()
{
   函数体(一堆命令的集合,来实现某个功能)
   echo hello
   echo world
}

函数中return说明:**

  1. return可以结束一个函数。类似于循环控制语句break(结束当前循环,执行循环体后面的代码)。
  2. return默认返回函数中最后一个命令状态值,也可以给定参数值,范围是0-256之间。
  3. 如果没有return命令,函数将返回最后一个指令的退出状态值。

2. 函数如何调用?

㈠ 当前命令行调用

[root@MissHou shell04]# cat fun1.sh 
#!/bin/bash
hello(){
echo "hello lilei $1"
hostname
}
menu(){
cat <<-EOF
1. mysql
2. web
3. app
4. exit
EOF
}

[root@MissHou shell04]# source fun1.sh 
[root@MissHou shell04]# . fun1.sh 

[root@MissHou shell04]# hello 888
hello lilei 888
MissHou.itcast.cc
[root@MissHou shell04]# menu
1. mysql
2. web
3. app
4. exit

㈡ 定义到用户的环境变量中

[root@MissHou shell05]# vim ~/.bashrc 
文件中增加如下内容:
hello(){
echo "hello lilei $1"
hostname
}
menu(){
cat <<-EOF
1. mysql
2. web
3. app
4. exit
EOF
}

注意:
当用户打开bash的时候会读取该文件

㈢ 脚本中调用

#!/bin/bash
#打印菜单
source ./fun1.sh
menu(){
cat <<-END
	h	显示命令帮助
	f	显示磁盘分区
	d	显示磁盘挂载
	m	查看内存使用
	u	查看系统负载
	q	退出程序
	END
}
menu		//调用函数

应用案例

具体需求:

  1. 写一个脚本收集用户输入的基本信息(姓名,性别,年龄),如不输入一直提示输入
  2. 最后根据用户的信息输出相对应的内容

思路:

  1. 交互式定义多个变量来保存用户信息 姓名、性别、年龄

  2. 如果不输一直提示输入

    • 循环直到输入字符串不为空 while 判断输入字符串是否为空
    • 每个信息都必须不能为空,该功能可以定义为一个函数,方便下面脚本调用
  3. 根据用户输入信息做出匹配判断

fun2.sh

#!/bin/env bash
#该函数实现用户如果不输入内容则一直循环直到用户输入为止,并且将用户输入的内容打印出来

input_fun(){
   input_var=""
   output_var=$1
   while [ -z $input_var ]
     do
        read -p "$output_var" input_var
     done
     echo $input_var
     return 9 
}

--------方式2 ,递归调用
#!/bin/bash
fun()
{
	read -p "$1" var
	if [ -z $var ];then
		fun $1
	else
		echo $var
	fi
}

调用方式1

[root@node2 shell105]# vim fun2.sh
[root@node2 shell105]# chmod +x fun2.sh 
[root@node2 shell105]# source fun2.sh 
[root@node2 shell105]# input_fun 请输入你的姓名
请输入你的姓名lucy
lucy

[root@node2 shell105]# echo $?
9
[root@node2 shell105]# name=$(input_fun 请输入姓名)
请输入姓名lucy
[root@node2 shell105]# echo $name
lucy

最终脚本为

#!/bin/env bash

input(){

var=""
tip=$1
while [ -z $var ]
do
   read -p $tip var 
done 
echo $var
return 9


}

name=`input 请输入姓名:`    ---或者写成name=$(input 请输入姓名:)
age=`input 请输入年龄:`
gender=`input 请输入性别:`

case $gender in 
man | M)
  if [ $age -le 35 -a $age -gt 18 ];then
    echo "中年大叔"
  elif [ $age -gt 35 ];then
    echo "快喝枸杞"
  else  
    echo "小少年"
   fi
;;
women | F)
  echo "这是个小姑娘"
;;
*)
  echo "无效性别"
;;
esac

3. 综合案例

1. 任务背景

现有的跳板机虽然实现了统一入口来访问生产服务器,yunwei用户权限太大可以操作跳板机上的所有目录文件,存在数据被误删的安全隐患,所以希望你做一些安全策略来保证跳板机的正常使用。

2. 具体要求

  1. 只允许yunwei用户通过跳板机远程连接后台的应用服务器做一些维护操作
  2. 公司运维人员远程通过yunwei用户连接跳板机时,跳出以下菜单供选择:
欢迎使用Jumper-server,请选择你要操作的主机:
3. DB1-Master
4. DB2-Slave
5. Web1
6. Web2
h. help
q. exit
  1. 当用户选择相应主机后,直接免密码登录成功
  2. 如果用户不输入一直提示用户输入,直到用户选择退出

3. 综合分析

  1. 将脚本放到yunwei用户家目录里的.bashrc文件里(/shell05/jumper-server.sh)
  2. 将菜单定义为一个函数[打印菜单],方便后面调用
  3. 用case语句来实现用户的选择【交互式定义变量】
  4. 当用户选择了某一台服务器后,进一步询问用户需要做的事情 case…esac 交互式定义变量
  5. 使用循环来实现用户不选择一直让其选择
  6. 限制用户退出后直接关闭终端 exit

4. 落地实现

#!/bin/bash
# jumper-server
# 定义菜单打印功能的函数
menu()
{
cat <<-EOF
欢迎使用Jumper-server,请选择你要操作的主机:
1. DB1-Master
2. DB2-Slave
3. Web1
4. Web2
h. help
q. exit
	EOF
}
# 屏蔽以下信号
#trap '' 1 2 3 19      
# 调用函数来打印菜单
menu
#循环等待用户选择
while true
do
# 菜单选择,case...esac语句
read -p "请选择你要访问的主机:" host
case $host in
	1)
	ssh root@10.1.1.1
	;;
	2)
	ssh root@10.1.1.2
	;;
	3)
	ssh root@10.1.1.3
	;;
	h)
	clear;menu
	;;
	q)
	exit
	;;
esac
done


将脚本放到yunwei用户家目录里的.bashrc里执行:
bash ~/jumper-server.sh
exit

进一步完善需求

为了进一步增强跳板机的安全性,工作人员通过跳板机访问生产环境,但是不能在跳板机上停留。

#!/bin/bash
#公钥推送成功
trap '' 1 2 3 19
#打印菜单用户选择
menu(){
cat <<-EOF
欢迎使用Jumper-server,请选择你要操作的主机:
1. DB1-Master
2. DB2-Slave
3. Web1
4. Web2
h. help
q. exit
EOF
}

#调用函数来打印菜单
menu
while true
do
read -p "请输入你要选择的主机[h for help]:" host

#通过case语句来匹配用户所输入的主机
case $host in
	1|DB1)
	ssh root@10.1.1.1
	;;
	2|DB2)
	ssh root@10.1.1.2
	;;
	3|web1)
	ssh root@10.1.1.250
	;;
	h|help)
	clear;menu
	;;
	q|quit)
	exit
	;;
esac
done

自己完善功能:
1. 用户选择主机后,需要事先推送公钥;如何判断公钥是否已推
2. 比如选择web1时,再次提示需要做的操作,比如:
clean log
重启服务
kill某个进程

将jumper-server.sh添加到当前运维账户下的~/.bashrc下

[yunwei@node2 ~]$ vim ~/.bashrc


# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=

# User specific aliases and functions
/home/yunwei/jumper-server.sh   --这里指定函数

这样当yunwei账户一登录,就会执行jumper-server.sh脚本

[root@node2 ~]# su - yunwei
上一次登录:三 1026 12:42:10 CST 2022pts/0 上
欢迎使用jumper-server,请选择你要操作的主机:
1.DB1-Master
2.DB2-Slave
3.Web1
4.Web2
h.help
q.exit
请输入你要选择的主机【h for help 】:
请输入你要选择的主机【h for help 】:q
[yunwei@node2 ~]$     ----退出函数,但是还是存在于yunwei账户下

当我们输入q的时候,程序会退出函数,但是我们想实现,一退出,就直接退出yunwei账户,一旦登录运维,就一直在不断询问要执行什么操作

解决办法

[yunwei@node2 ~]$ vim ~/.bashrc 

# User specific aliases and functions
/home/yunwei/jumper-server.sh
exit   ---这个地方增加exit即可,也就是jumper-server.sh脚本一旦执行完以后,就直接退出当前用户

这样更改以后,我们输入q以后,就直接退出yunwei账户了

[root@node2 ~]# su - yunwei
上一次登录:三 1026 13:09:47 CST 2022pts/2 上
欢迎使用jumper-server,请选择你要操作的主机:
1.DB1-Master
2.DB2-Slave
3.Web1
4.Web2
h.help
q.exit
请输入你要选择的主机【h for help 】:q
[root@node2 ~]#    ---退回到之前的用户下了

但是发现我们输入ctrl+c依然可以退出jumper-server.sh 中的函数

请输入你要选择的主机【h for help 】:^C[yunwei@node2 ~]$ 
[yunwei@node2 ~]$ 

这些快捷键其实也是信号,常见信号如下

1) SIGHUP 			重新加载配置    
2) SIGINT			键盘中断^C
3) SIGQUIT      	键盘退出
9) SIGKILL		 	强制终止
15) SIGTERM	    	终止(正常结束),缺省信号
18) SIGCONT	   	继续
19) SIGSTOP	   	停止
20) SIGTSTP     	暂停^Z

屏蔽用

trap ‘’ 1 2 3 19
trap : 信号代码1 信号代码2 … 信号代码N
trap ‘’ 或者trap :表示什么都不做,当遇到后面信号的时候,什么都不做

在shell脚本调用menu方法以前,加上

....忽略
trap : 1 2 3 19
menu
...... 忽略

这样,再输入ctrl+c以后,就不会退出了

请输入你要选择的主机【h for help 】:^C
请输入你要选择的主机【h for help 】:^C
请输入你要选择的主机【h for help 】:^C
请输入你要选择的主机【h for help 】:

三、正则表达式

支持正则表达式的程序如:locate |find| vim| grep| sed |awk

第一类正则

㈠ 正则中普通常用的元字符

元字符功能备注
.匹配除了换行符以外的任意单个字符
*前导字符出现0次或连续多次
.*任意长度字符ab.*
^行首(以…开头)^root
$行尾(以…结尾)bash$
^$空行
[]匹配括号里任意单个字符或一组单个字符[abc]
[^]匹配不包含括号里任一单个字符或一组单个字符[^abc]
1匹配以括号里任意单个字符或一组单个字符开头2
^[^]匹配不以括号里任意单个字符或一组单个字符开头^[^abc]
# cat 1.txt
ggle
gogle
google
gooogle
goooooogle
gooooooogle
taobao.com
taotaobaobao.com

jingdong.com
dingdingdongdong.com
10.1.1.1
Adfjd8789JHfdsdf/
a87fdjfkdLKJK
7kdjfd989KJK;
bSKJjkksdjf878.
cidufKJHJ6576,

hello world
helloworld yourself
[root@node2 shell105]# grep 'g.' 1.txt
ggle
gogle
google
gooogle
goooooogle
gooooooogle
jingdong.com
dingdingdongdong.com

[root@node2 shell105]# grep 'g*' 1.txt
ggle
gogle
google
gooogle
goooooogle
gooooooogle
taobao.com
taotaobaobao.com

jingdong.com
dingdingdongdong.com
10.1.1.1
Adfjd8789JHfdsdf/
a87fdjfkdLKJK
7kdjfd989KJK;
bSKJjkksdjf878.
cidufKJHJ6576,

hello world
helloworld yourself
[root@node2 shell105]# 

发现空行有2行

[root@node2 shell105]# grep '^$' 1.txt |wc -l
2
[root@node2 shell105]# grep 'go*' 1.txt
ggle
gogle
google
gooogle
goooooogle
gooooooogle
jingdong.com
dingdingdongdong.com
[root@node2 shell105]# grep 'go.*' 1.txt
gogle
google
gooogle
goooooogle
gooooooogle
[root@node2 shell105]# 

过滤以a开头,或者以b开头,或者以c开头的

[root@node2 shell105]# grep ^[abc] 1.txt 
a87fdjfkdLKJK
bSKJjkksdjf878.
cidufKJHJ6576,


过滤不以a\b\c开头的 个数
[root@node2 shell105]# grep ^[^abc] 1.txt |wc -l

㈡ 正则中其他常用元字符

元字符功能备注
\<取单词的头
\>取单词的尾
\< \>精确匹配
\{n\}匹配前导字符连续出现n次
\{n,\}匹配前导字符至少出现n次
\{n,m\}匹配前导字符出现n次与m次之间
\( \)保存被匹配的字符
\d匹配数字(grep -P[0-9]
\w匹配字母数字下划线(grep -P[a-zA-Z0-9_]
\s匹配空格、制表符、换页符(grep -P[\t\r\n]
需求:将10.1.1.1替换成10.1.1.254

1)vim编辑器支持正则表达式
# vim 1.txt
:%s#\(10.1.1\).1#\1.254#g 
:%s/\(10.1.1\).1/\1.254/g 

2)sed支持正则表达式【后面学】
# sed -n 's#\(10.1.1\).1#\1.254#p' 1.txt
10.1.1.254

说明:
找出含有10.1.1的行,同时保留10.1.1并标记为标签1,之后可以使用\1来引用它。
最多可以定义9个标签,从左边开始编号,最左边的是第一个。


需求:将helloworld yourself 换成hellolilei myself

# vim 1.txt
:%s#\(hello\)world your\(self\)#\1lilei my\2#g

# sed -n 's/\(hello\)world your\(self\)/\1lilei my\2/p' 1.txt 
hellolilei myself

# sed -n 's/helloworld yourself/hellolilei myself/p' 1.txt 
hellolilei myself
# sed -n 's/\(hello\)world your\(self\)/\1lilei my\2/p' 1.txt 
hellolilei myself

Perl内置正则:
\d      匹配数字  [0-9]
\w      匹配字母数字下划线[a-zA-Z0-9_]
\s      匹配空格、制表符、换页符[\t\r\n]

# grep -P '\d' 1.txt
# grep -P '\w' 2.txt
# grep -P '\s' 3.txt

实操
匹配单词的头

[root@node2 shell105]# grep \<hel 1.txt ----错误
[root@node2 shell105]# grep '\<hel' 1.txt 
hello world
helloworld yourself

匹配单词的尾

[root@node2 shell105]# grep 'rld\>' 1.txt 
hello world
helloworld yourself

至少出现几次

[root@node2 shell105]# grep 'g\{1\}' 1.txt 
ggle
gogle
google
gooogle
goooooogle
gooooooogle
jingdong.com
dingdingdongdong.com
[root@node2 shell105]# grep 'g\{2\}' 1.txt 
ggle

^ 和<的区别

[root@node2 shell105]# grep '^you' 1.txt 
[root@node2 shell105]# grep '\<you' 1.txt
helloworld yourself

数字出现 2到4次

[root@node2 shell105]# grep '[0-9]\{2,4\}' 1.txt 
10.1.1.1
Adfjd8789JHfdsdf/
a87fdjfkdLKJK
7kdjfd989KJK;
bSKJjkksdjf878.
cidufKJHJ6576,
[root@node2 shell105]# grep '[0-9]\{2\}\.[0-9]\{1\}\.[0-9]\{1\}\.[0-9]\{1\}' 1.txt 
10.1.1.1

注意,  \ 转义符号

vim 打开文件,全局搜索10.1.1.1,并全量替换为10.1.1.254

%s 全文搜索
/g全局替换

在这里插入图片描述
回车以后,
在这里插入图片描述
就更改数据了,然后:wq!保存退出

....忽略
10.1.1.254
....忽略
:%s/\(10.1.1\).254/\1.1/g  

回车,就会把10.1.1保存为1,并且替换为\1.1 这样就替换为了10.1.1.1了

[root@node2 shell105]# grep -P '\d' 1.txt 
10.1.1.254
Adfjd8789JHfdsdf/
a87fdjfkdLKJK
7kdjfd989KJK;
bSKJjkksdjf878.
cidufKJHJ6576,



[root@node2 shell105]# grep -P '\w' 1.txt 
ggle
gogle
google
gooogle
goooooogle
gooooooogle
taobao.com
taotaobaobao.com
jingdong.com
dingdingdongdong.com
10.1.1.254
Adfjd8789JHfdsdf/
a87fdjfkdLKJK
7kdjfd989KJK;
bSKJjkksdjf878.
cidufKJHJ6576,
hello world
helloworld yourself

等同于  grep '[0-9a-zA-Z]' 1.txt 


 grep -P '\s' 1.txt
 可以过滤出存在空格,制表符的行信息

㈢ 扩展类正则常用元字符

丑话说在前面:

我说我比较特殊,你要相信!否则我错给你看😏

  • grep你要用我,必须加 -E 或者 让你兄弟egrep来找我

  • sed你要用我,必须加 -r

扩展元字符功能备注
+匹配一个或多个前导字符bo+ 匹配boo、 bo ,不能匹配ooo
?匹配零个或一个前导字符bo? 匹配b、 bo
|匹配a或b
()组字符(看成整体)(my|your)self:表示匹配myself或匹配yourself
{n}前导字符重复n次
{n,}前导字符重复至少n次
{n,m}前导字符重复n到m次

举例说明

# grep "root|ftp|adm" /etc/passwd
# egrep "root|ftp|adm" /etc/passwd
# grep -E "root|ftp|adm" /etc/passwd

# grep -E 'o+gle' test.txt 
# grep -E 'o?gle' test.txt 

# egrep 'go{2,}' 1.txt
# egrep '(my|your)self' 1.txt


使用正则过滤出文件中的IP地址:
# grep '[0-9]\{2\}\.[0-9]\{1\}\.[0-9]\{1\}\.[0-9]\{1\}' 1.txt 
10.1.1.1
# grep '[0-9]{2}\.[0-9]{1}\.[0-9]{1}\.[0-9]{1}' 1.txt 
# grep -E '[0-9]{2}\.[0-9]{1}\.[0-9]{1}\.[0-9]{1}' 1.txt 
10.1.1.1
# grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' 1.txt 
10.1.1.1
# grep -E '([0-9]{1,3}\.){3}[0-9]{1,3}' 1.txt 
10.1.1.1

实操

在这里插入图片描述

在这里插入图片描述
?匹配0次或者1次

在这里插入图片描述
点号 . 表示除了换行符以外的任意单个字符

在这里插入图片描述
在这里插入图片描述

第二类正则

表达式功能示例
[:alnum:]字母与数字字符[[:alnum:]]+
[:alpha:]字母字符(包括大小写字母)[[:alpha:]]{4}
[:blank:]空格与制表符[[:blank:]]*
[:digit:]数字[[:digit:]]?
[:lower:]小写字母[[:lower:]]{4,}
[:upper:]大写字母[[:upper:]]+
[:punct:]标点符号[[:punct:]]
[:space:]包括换行符,回车等在内的所有空白[[:space:]]+
[root@server shell05]# grep -E '^[[:digit:]]+' 1.txt
[root@server shell05]# grep -E '^[^[:digit:]]+' 1.txt
[root@server shell05]# grep -E '[[:lower:]]{4,}' 1.txt

出现0次或者1次数值的
在这里插入图片描述
在这里插入图片描述

总结

把握一个原则,让你轻松搞定可恶的正则符号:

  1. 我要找什么?
    • 找数字 [0-9]
    • 找字母 [a-zA-Z]
    • 找标点符号 [[:punct:]]
  2. 我要如何找?看心情找
    • 以什么为首 ^key
    • 以什么结尾 key$
    • 包含什么或不包含什么 [abc] ^[abc] [^abc] ^[^abc]
  3. 我要找多少呀?
    • 找前导字符出现0次或连续多次 ab*
    • 找任意单个(一次)字符 ab.
    • 找任意字符 ab.*
    • 找前导字符连续出现几次 {n} {n,m} {n,}
    • 找前导字符出现1次或多次 go+
    • 找前到字符出现0次或1次 go?

元字符:在正则中,具有特殊意义的专用字符,如: 星号(*)、加号(+)等

前导字符:元字符前面的字符叫前导字符

元字符功能示例
*前导字符出现0次或者连续多次ab* abbbb
.除了换行符以外,任意单个字符ab. ab8 abu
.*任意长度的字符ab.* adfdfdf
[]括号里的任意单个字符或一组单个字符[abc][0-9][a-z]
[^]不匹配括号里的任意单个字符或一组单个字符[^abc]
3匹配以括号里的任意单个字符开头4
^[^]不匹配以括号里的任意单个字符开头
^行的开头^root
$行的结尾bash$
^$空行
\{n\}和{n}前导字符连续出现n次[0-9]\{3\}
\{n,\}和{n,}前导字符至少出现n次[a-z]{4,}
\{n,m\}和{n,m}前导字符连续出现n-m次go{2,4}
\<\>精确匹配单词\<hello\>
\(\)保留匹配到的字符\(hello\)
+前导字符出现1次或者多次[0-9]+
?前导字符出现0次或者1次go?
|^root|^ftp
()组字符(hello|world)123
\dperl内置正则grep -P \d+
\w匹配字母数字下划线

综合正则练习

1、查找不以大写字母开头的行(三种写法)。
grep '^[^A-Z]' 2.txt
grep -v '^[A-Z]' 2.txt
grep '^[^[:upper:]]' 2.txt
2、查找有数字的行(两种写法)
grep '[0-9]' 2.txt
grep -P '\d' 2.txt
3、查找一个数字和一个字母连起来的
grep -E '[0-9][a-zA-Z]|[a-zA-Z][0-9]' 2.txt
4、查找不以r开头的行
grep -v '^r' 2.txt
grep '^[^r]' 2.txt
5、查找以数字开头的
grep '^[0-9]' 2.txt
6、查找以大写字母开头的
grep '^[A-Z]' 2.txt
7、查找以小写字母开头的
grep '^[a-z]' 2.txt
8、查找以点结束的
grep '\.$' 2.txt
9、去掉空行
grep -v '^$' 2.txt
10、查找完全匹配abc的行
grep '\<abc\>' 2.txt
11、查找A后有三个数字的行
grep -E 'A[0-9]{3}' 2.txt
grep  'A[0-9]\{3\}' 2.txt
12、统计root在/etc/passwd里出现了几次
grep -o 'root' 1.txt |wc -l

13、用正则表达式找出自己的IP地址、广播地址、子网掩码
ifconfig eth0|grep Bcast|grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'
ifconfig eth0|grep Bcast| grep -E -o '([0-9]{1,3}.){3}[0-9]{1,3}'
ifconfig eth0|grep Bcast| grep -P -o '\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}'
ifconfig eth0|grep Bcast| grep -P -o '(\d{1,3}.){3}\d{1,3}'
ifconfig eth0|grep Bcast| grep -P -o '(\d+.){3}\d+'

# egrep --color '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' /etc/sysconfig/network-scripts/ifcfg-eth0
IPADDR=10.1.1.1
NETMASK=255.255.255.0
GATEWAY=10.1.1.254

# egrep --color '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' /etc/sysconfig/network-scripts/ifcfg-eth0 
IPADDR=10.1.1.1
NETMASK=255.255.255.0
GATEWAY=10.1.1.254


14、找出文件中的ip地址并且打印替换成172.16.2.254
grep -o -E '([0-9]{1,3}\.){3}[0-9]{1,3}' 1.txt |sed -n 's/192.168.0.\(254\)/172.16.2.\1/p'

15、找出文件中的ip地址
grep -o -E '([0-9]{1,3}\.){3}[0-9]{1,3}' 1.txt

16、找出全部是数字的行
grep -E '^[0-9]+$' test
17、找出邮箱地址
grep -E '^[0-9]+@[a-z0-9]+\.[a-z]+$'


grep --help:
匹配模式选择:
Regexp selection and interpretation:
  -E, --extended-regexp     扩展正则
  -G, --basic-regexp        基本正则
  -P, --perl-regexp         调用perl的正则
  -e, --regexp=PATTERN      use PATTERN for matching
  -f, --file=FILE           obtain PATTERN from FILE
  -i, --ignore-case         忽略大小写
  -w, --word-regexp         匹配整个单词
  

四 作业

要求如下

  1. 用户输入web服务器的IP、域名以及数据根目录
  2. 如果用户不输入则一直提示输入,直到输入为止
  3. 当访问www.test.cc时可以访问到数据根目录里的首页文件“this is test page”

参考脚本:

参考:
#!/bin/bash
conf=/etc/httpd/conf/httpd.conf
input_fun()
{
  input_var=""
  output_var=$1
  while [ -z $input_var ]
	do
	read -p "$output_var" input_var
	done
	echo $input_var
}
ipaddr=$(input_fun "Input Host ip[192.168.0.1]:")
web_host_name=$(input_fun "Input VirtualHostName [www.test.cc]:")
root_dir=$(input_fun "Input host Documentroot dir:[/var/www/html]:")

[ ! -d $root_dir ] && mkdir -p $root_dir
chown apache.apache $root_dir && chmod 755 $root_dir
echo this is $web_host_name > $root_dir/index.html
echo "$ipaddr $web_host_name" >> /etc/hosts

[ -f $conf ] && cat >> $conf <<end
NameVirtualHost $ipaddr:80
<VirtualHost $ipaddr:80>
	ServerAdmin webmaster@$web_host_name
	DocumentRoot $root_dir
	ServerName $web_host_name
	ErrorLog logs/$web_host_name-error_log
	CustomLog logs/$web_host_name-access_loh common
</VirtualHost>
end

  1. ↩︎

  2. abc ↩︎

  3. ↩︎

  4. abc ↩︎

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值