shell(三)

case语句

case语句为多选择语句。可以用case语句匹配一个值与一个模式,如果匹配成功,执行相 匹配的命令。

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

示例1:

当给程序传入start、stop、reload三个不同参数时分别执行相应命令。

#!/bin/bash
case $1 in
    start|S)
    echo "service is running..."
    ;;
    stop|P)
    echo "service is stoped."
    ;;
    reload|R)
    echo "service is reloading..."
    ;;
    *)
    echo "usage:$0 start|stop|reload..."
    ;;
esac

示例2:

模拟一个多任务维护界面。当执行某程序时先显示总菜单,然后进行相应选择后进入子菜单。

#!/bin/bash
echo "**************************"
echo "******欢迎进入总菜单******"
echo "      操作类型        "
echo "      1——系统       "
echo "      2——程序       "
echo "      3——数据库      "
echo "      0——退出       "
echo "**************************"
read -p "请选择操作类型:" choose
echo
    case "$choose" in
        0)
        echo "谢谢使用,如有问题联系管理员:root@localhost"
        ;;
        1)
        echo "欢迎进入红帽子系统"
        ;;
        2)
        echo "程序维护"
        ;;
        3)
        clear
        echo "*******欢迎来到子菜单*****"
        echo "**********操作类型********"
        echo "      1——备份       "
        echo "      2——维护       "
        echo "      3——优化       "
        echo "      0——退出       "
        echo "**************************"
            read -p "请选择操作类型:" choose1
            case "$choose1" in
                1)
                echo backup
                ;;
                0)
                echo "谢谢使用!"
                ;;
                *)
                echo "请选择操作类型"
                ;;
            esac
            ;;
        *)
        echo "how are you?"
        ;;
esac 

函数

shell中允许将一组命令集合或语句形成一段可用代码,这些代码块称为shell函数。给这段代码起个名字称为函数名,后续可以直接调用该段代码。

语法结构:
function_name() {
        command
        command
}
​
​
function function_name() {
        command
        command
}
​
函数名()
{
 ......
}
function 函数名()
{
 .......
 command1
 command2
}
​
函数中return说明:
1.return可以结束一个函数,类似于前面讲的循环控制语句break(结束当前循环,执行循环体后面的代码)
2.return默认返回函数中最后一个命令的退出状态,也可以给定参数值,该参数值的范围是0-256之间。
3.如果没有return命令,函数将返回最后一个Shell的退出值。

函数的调用

当前命令行调用

[root@server shell03]# cat fun1.sh 
#!/bin/bash
hello(){
echo welcome to itcast
return 1
echo skdfjkdjf
}
​
function world(){
echo wa hahaha
}
​
[root@server shell03]# source fun1.sh   //读取函数定义文件
[root@server shell03]# hello 
welcome to itcast
[root@server shell03]# world
wa hahaha

 定义到用户的环境变量中

[stu1@server ~]$ cat .bashrc 
# .bashrc
​
# Source global definitions
if [ -f /etc/bashrc ]; then
    . /etc/bashrc
fi
​
source /tmp/fun1.sh
# User specific aliases and functions
​
或者
# .bashrc
​
# Source global definitions
if [ -f /etc/bashrc ]; then
    . /etc/bashrc
fi
​
# User specific aliases and functions
hello (){
  echo welcome to itcast
}

脚本中调用

#!/bin/bash
hello(){
echo 888888
}
case $1 in
        start|S)
        hello
        echo "service is running..."
        ;;
        stop|P)
        echo "service is stoped."
        ;;
        reload|R)
        hello;echo "service is reloading..."
        ;;
        *)
        echo "usage:$0 start|stop|reload..."
        ;;
esac
​
或者
source /xxxx/fun1.sh
...

应用案例

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

思路:

  • 循环直到输入字符串不为空

  • 根据用户输入信息做出匹配判断

#!/bin/bash
input_fun()
{
  input_var=""
  output_var=$1
  while [ -z $input_var ]
    do
    read -p "$output_var" input_var
    done
    echo $input_var
}
​
name=$(input_fun "Input your name:")
sex=$(input_fun "Input your sex(男or女):")
age=$(input_fun "Input your age:")
​
case $sex in|man)
    if [ $age -ge 20 -a $age -le 35 ];then
        echo "$name先生,你好帅"
    elif [ $age -gt 35 ];then
        echo "$name大叔,你油腻了吗?"
    else
        echo "$name小伙子,前途无量"
    fi
    ;;
    女|lady|woman)
    echo "$name小姐姐你好漂亮"
    ;;
    *)
    echo "你是泰国来的吗?"
    ;;
esac

 



应用案例二

  1. 输入一个等级(A-E),查看每个等级的成绩;如:输入A,则显示“90分~100分”,依次类推

  2. 模拟2人第一次相亲的场景,使用read让用户输入它的名字,性别,年龄(年龄放在性别判断后);在case里面再嵌套case菜单,使之选项更丰富。

要求:

1)

  • 对性别进行判断,如果不输入男或者女,则显示”你是泰国来的吗?“

  • 如果是男的,对其年龄进行判断。

2)

  • 如果男的年龄大于等于18岁则显示“某某先生,你结婚了吗?”;

  • 如果对方回答结了或者yes,则显示“结了你来这凑什么热闹”;

  • 如果对方回答没有或者no,再次询问“那你有房有车吗?”;

  • 如果既不说结了也不说没结则显示:“你Y的到底结没结婚啊?”

  • 如果回答有房有车,则显示”咱去民政局领证吧“;

  • 如果回答没有,则显示“不好意思,我去下洗手间。”;

  • 如果既不说有又不说没有,则显示“别浪费时间,请正面回答”。

  • 如果男的年龄小于18岁,则显示“某某某你个小毛孩也来这凑热闹啦”

3)如果是女的,并且年龄大于等于18岁,则显示”某某女士你好“;否则显示”某某小姐你好“

 

参考:
#!/bin/bash
read -p "输入你的姓名:" name
read -p "输入你的性别:" gender
​
case "$gender" in|man|male|boy )
        read -p "输入你的年龄:" age
        if [ $age -ge 18 ];then
            read -p "$name先生,你结婚了吗?" anwser
                case "$anwser" in
                    结了|有|yes )
                        echo "结了你还来干嘛?"
                        ;;
                    没结|没有|没|no )
                        read -p "有房有车吗?" anwser2
                        case "$anwser2" in
                            有)
                                echo "咱就直接去民政局领证吧"
                                ;;
                            没有 )
                                echo "不好意思,我去下洗手间"
                                ;;
                            * )
                                echo "别浪费时间,请正面回答"
                        esac
                        ;;
                    * )
                        echo "你到底结没结?"
                esacelse
            echo "$name小子"
        fi
        ;;
    女|woman|female|girl|lady )
        read -p "输入你的年龄:" age
        if [ $age -ge 18 ];then
            echo "$name女士"
        else
            echo "$name小姐"
        fi
        ;;
    * )
        echo "你是泰国来的吗?"
esac
​
该程序有个bug:如果输入年龄为负数或者0也是可以的,如何修复bug?增加一个条件:如果输入的年龄小于等于10则显示:”不跟你玩了。。。“
​
在最后加入如下语句即可:
if [ $age -ge 18 ];then
                        echo "$name女士"
                elif
                   [ $age -le 10 ];then
                        echo "不跟你玩了"
                     exit 1
                else
                        echo "$name小姐"
                fi
                ;;
        * )
                echo "你是泰国来的吗?"esac

正则表达式

什么是正则表达式

正则表达式(Regular Expression、regex或regexp,缩写为RE),也译为正规表示法、常规表示法,是一种字符模式,用于在查找过程中匹配指定的字符。

许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。

正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的。

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

第一类正则

元字符:指那些在正则表达式中具有特殊意义的专用字符,如:点(.) 星(*) 问号(?)等

前导字符:即位于元字符前面的字符

常用元字符

1).        任意单个字符,除了换行符 
(2)*        前导字符出现0次或连续多次  ab*能匹配“a”,“ab”以及“abb”,但是不匹配“cb”
(3).*        任意长度的字符
(4)^        行的开头
(5)$        行的结尾
(6)^$        空行

(7)[ ]        匹配指定字符组内的任一字符   
(8) [^]        匹配不在指定字符组内的任一字符 

(9)^[]        匹配以指定字符组内的任一字符开头   
(10)^[^]    匹配不以指定字符组内的任一字符开头   

(11)\<        取单词的头
(12)\>        取单词的尾
(13)\<\>    精确匹配符号 

(14)\{n\}    匹配前导字符连续出现n次 
(15)\{n,\}    匹配前导字符至少出现n次 
(16)\{n,m\}    匹配前导字符出现n次与m次之间 

 (17) \(xxx\)    保存被匹配的字符


将192.168.0.254 换成 192.168.1.254
vim 1.txt
:%s#\(192\.168\)\.0\.\(254\)#\1\.100\.\2    //底行模式下匹配

# sed -n 's#\(192\.168\)\.0\.254#\1\.1\.254#p'      
找出含有192.168的行,同时保留192.168并标记为标签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

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

#grep -P '\d' test.txt
#grep -P '\w' test.txt
#grep -P '\s' test.txt

扩展类的正则表达式 grep -E 或则 egerp

扩展正则表达式元字符
+            匹配一个或多个前导字符
?            匹配零个或一个前导字符
a|b            匹配a或b
()            组字符       hello myself yourself     (my|your)self
x{m}        前导字符x重复m次
x{m,}        前导字符x重复至少m次
x{m,n}        前导字符x重复m到n次

# 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

[root@server shell03]# grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' 1.txt 
10.1.1.1
[root@server shell03]# grep -E '([0-9]{1,3}\.){3}[0-9]{1,3}' 1.txt 
10.1.1.1

[root@server shell03]# grep -P '\d+\.\d+\.\d+\.\d+' 1.txt 
10.1.1.1
[root@server shell03]# grep -P '(\d+\.){3}\d+' 1.txt 
10.1.1.1
[root@server shell03]# grep -P '(\d+\.)+\d+' 1.txt 
10.1.1.1
[root@server shell03]# grep -P '(\d+\.){3}\d+' 1.txt 
10.1.1.1
[root@server shell03]# grep -P '(\d{1,3}\.){3}\d+' 1.txt 
10.1.1.1

第二类正则

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

案例

写一个自动搭建apache服务的脚本,要求如下:

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

 

 

 

posted @ 2020-04-21 22:37  鱼虫光  阅读(450)  评论(0编辑  收藏  举报