這篇文章主要為大家詳細介紹了Shell編程中的case語句與函數,文中示例代碼介紹的非常詳細,非常適合初學者入門,感興趣的小伙伴們可以參考一下。
一、case語句
1.語法結構
2.應用案例
1)腳本傳不同值做不同事
2)根據用戶需求選擇做事
二、函數
1.什么是函數?
2.如何定義函數?
3.函數如何調用?
1)當前命令行調用
2)定義到用戶的環境變量中
3)腳本中調用
三、綜合案例
1.任務背景
2.具體要求
3.綜合分析
4.落地實現
四、正則表達式
1.正則表達式是什么?
2.正則能干什么?
3.正則當中名詞解釋
4.第一類正則表達式
1)正則中普通常用的元字符
2)正則中其他常用元字符
3)擴展類正則常用元字符
5.第二類正則
6.正則表達式總結
五、正則元字符一欄表
六、正則練習作業
1.文件準備
2.具體要求
七、課后作業
腳本搭建web服務
說明:pattern表示需要匹配的模式
case var in 定義變量;var代表是變量名
pattern 1) 模式1;用 | 分割多個模式,相當于or
command1 需要執行的語句
;; 兩個分號代表命令結束
pattern 2)
command2
;;
pattern 3)
command3
;;
*) default,不滿足以上模式,默認執行*)下面的語句
command4
;;
esac esac表示case語句結束
具體需求:當給程序傳入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
###㈢ 菜單提示讓用戶選擇需要做的事
具體需求:
模擬一個多任務維護界面;當執行程序時先顯示總菜單,然后進行選擇后做相應維護監控操作
**********請選擇*********
h 顯示命令幫助
f 顯示磁盤分區
d 顯示磁盤掛載
m 查看內存使用
u 查看系統負載
q 退出程序
*************************
思路:
落地實現:
#!/bin/env bash
cat <<-EOF
h 顯示命令幫助
f 顯示磁盤分區
d 顯示磁盤掛載
m 查看內存使用
u 查看系統負載
q 退出程序
EOF
#!/bin/bash
#打印菜單
cat <<-EOF
h 顯示命令幫助
f 顯示磁盤分區
d 顯示磁盤掛載
m 查看內存使用
u 查看系統負載
q 退出程序
EOF
#讓用戶輸入需要的操作
while true
do
read -p "請輸入需要操作的選項[f|d]:" var1
case $var1 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:
函數名()
{
函數體(一堆命令的集合,來實現某個功能)
}
方法2:
function 函數名()
{
函數體(一堆命令的集合,來實現某個功能)
echo hello
echo world
}
函數中==return==說明:
[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 //調用函數
##4. 應用案例
具體需求:
思路:
如果不輸一直提示輸入
代碼實現:
#!/bin/bash
#該函數實現用戶如果不輸入內容則一直循環直到用戶輸入為止,并且將用戶輸入的內容打印出來
input_fun()
{
input_var=""
output_var=$1
while [ -z $input_var ]
do
read -p "$output_var" input_var
done
echo $input_var
}
input_fun 請輸入你的姓名:
或者
#!/bin/bash
fun()
{
read -p "$1" var
if [ -z $var ];then
fun $1
else
echo $var
fi
}
#調用函數并且獲取用戶的姓名、性別、年齡分別賦值給name、sex、age變量
name=$(input_fun 請輸入你的姓名:)
sex=$(input_fun 請輸入你的性別:)
age=$(input_fun 請輸入你的年齡:)
#根據用戶輸入的性別進行匹配判斷
case $sex in
man)
if [ $age -gt 18 -a $age -le 35 ];then
echo "中年大叔你油膩了嗎?加油"
elif [ $age -gt 35 ];then
echo "保溫杯里泡枸杞"
else
echo "年輕有為。。。"
fi
;;
woman)
xxx
;;
*)
xxx
;;
esac
擴展延伸:
描述以下代碼含義:
:()
{
:|:&
}
:
現有的跳板機雖然實現了統一入口來訪問生產服務器,yunwei用戶權限太大可以操作跳板機上的所有目錄文件,存在數據被誤刪的安全隱患,所以希望你做一些安全策略來保證跳板機的正常使用。
歡迎使用Jumper-server,請選擇你要操作的主機:
1. DB1-Master
2. DB2-Slave
3. Web1
4. Web2
h. help
q. exit
#!/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某個進程
回顧信號:
1) SIGHUP 重新加載配置
2) SIGINT 鍵盤中斷^C
3) SIGQUIT 鍵盤退出
9) SIGKILL 強制終止
15) SIGTERM 終止(正常結束),缺省信號
18) SIGCONT 繼續
19) SIGSTOP 停止
20) SIGTSTP 暫停^Z
正則表達式(Regular Expression、regex或regexp,縮寫為RE),也譯為正規表示法、常規表示法,是一種字符模式,用于在查找過程中==匹配指定的字符==。
許多程序設計語言都支持利用正則表達式進行字符串操作。例如,在Perl中就內建了一個功能強大的正則表達式引擎。
正則表達式這個概念最初是由Unix中的工具軟件(例如sed和grep)普及開的。
支持正則表達式的程序如:locate |find| vim| grep| sed |awk
元字符
指那些在正則表達式中具有特殊意義的==專用字符==,如:點(.) 星(*) 問號(?)等
前導字符
位于元字符前面的字符. ab**==c==* aoo==o==.**
元字符 | 功能 | 備注 |
---|---|---|
. | 匹配除了換行符以外的==任意單個==字符 | |
* | ==前導字符==出現==0==次或==連續多次== | |
.* | 任意長度字符 | ab.* |
^ | 行首(以...開頭) | ^root |
$ | 行尾(以...結尾) | bash$ |
^$ | 空行 | |
[] | 匹配括號里任意單個字符或一組單個字符 | [abc] |
[^] | 匹配不包含括號里任一單個字符或一組單個字符 | [^abc] |
^[] | 匹配以括號里任意單個字符或一組單個字符開頭 | ^[abc] |
\^[\^] | 匹配不以括號里任意單個字符或一組單個字符開頭 | \^[^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
元字符 | 功能 | 備注 |
---|---|---|
\< | 取單詞的頭 | |
\> | 取單詞的尾 | |
\< \> | 精確匹配 | |
\{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
==丑話說在前面:==
我說我比較特殊,你要相信!否則我錯給你看:smirk:
grep你要用我,必須加 ==-E== 或者 讓你兄弟egrep
來找我
擴展元字符 | 功能 | 備注 |
---|---|---|
+ | 匹配一個或多個前導字符 | bo+ 匹配boo、 bo |
? | 匹配零個或一個前導字符 | 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
表達式 | 功能 | 示例 |
---|---|---|
[: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次或者連續多次 | ab* abbbb |
. | 除了換行符以外,任意單個字符 | ab. ab8 abu |
.* | 任意長度的字符 | ab.* adfdfdf |
[] | 括號里的任意單個字符或一組單個字符 | [abc][0-9][a-z] |
[^] | 不匹配括號里的任意單個字符或一組單個字符 | [^abc] |
^[] | 匹配以括號里的任意單個字符開頭 | ^[abc] |
\^[^] | 不匹配以括號里的任意單個字符開頭 | |
^ | 行的開頭 | ^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 |
\d | perl內置正則 | grep -P \d+ |
\w | 匹配字母數字下劃線 |
# vim test.txt
Aieur45869Root0000
9h847RkjfkIIIhello
rootHllow88000dfjj
8ikuioerhfhupliooking
hello world
192.168.0.254
welcome to uplooking.
abcderfkdjfkdtest
rlllA899kdfkdfj
iiiA848890ldkfjdkfj
abc
12345678908374
123456@qq.com
123456@163.com
abcdefg@itcast.com23ed
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 匹配整個單詞
要求如下:
參考腳本:
參考:
#!/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
關于Shell編程中的case語句與函數就分享到這里了,希望以上內容可以對大家有一定的參考價值,可以學以致用。如果喜歡本篇文章,不妨把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。