個(gè)人專題目錄
?
1. Shell解析器
- Linux提供的Shell解析器有:
$ cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/bin/dash
/bin/tcsh
/bin/csh
- bash和sh的關(guān)系
$ ll /bin | grep bash
-rwxr-xr-x. 1 root root 941880 5月 11 2016 bash
lrwxrwxrwx. 1 root root 4 5月 27 2017 sh -> bash
- Centos默認(rèn)的解析器是bash
$ echo $SHELL
/bin/bash
2. Shell腳本入門
- 腳本格式
腳本以#!/bin/bash開(kāi)頭(指定解析器)這一行決定了腳本可以像一個(gè)獨(dú)立的可執(zhí)行文件一樣執(zhí)行,而不用在終端之前輸入sh
,bash
,python
,php
等。
- 第一個(gè)Shell腳本:helloworld
- 需求:創(chuàng)建一個(gè)Shell腳本,輸出helloworld
- 案例實(shí)操:
$ touch helloworld.sh
$ vi helloworld.sh
在helloworld.sh中輸入如下內(nèi)容
#!/bin/bash
echo "helloworld"
- 腳本的常用執(zhí)行方式
第一種:采用bash或sh+腳本的相對(duì)路徑或絕對(duì)路徑(不用賦予腳本+x權(quán)限)
# sh+腳本的相對(duì)路徑
$ sh helloworld.sh
#sh+腳本的絕對(duì)路徑
$ sh /home/xubh/datas/helloworld.sh
helloworld
#bash+腳本的相對(duì)路徑
$ bash helloworld.sh
Helloworld
#bash+腳本的絕對(duì)路徑
$ bash /home/xubh/datas/helloworld.sh
Helloworld
第二種:采用輸入腳本的絕對(duì)路徑或相對(duì)路徑執(zhí)行腳本(必須具有可執(zhí)行權(quán)限+x)
# 首先要賦予helloworld.sh 腳本的+x權(quán)限
$ chmod 777 helloworld.sh
# 執(zhí)行腳本
# 相對(duì)路徑
$ ./helloworld.sh
Helloworld
# 絕對(duì)路徑
$ /home/xubh/datas/helloworld.sh
Helloworld
注意:第一種執(zhí)行方法,本質(zhì)是bash解析器幫你執(zhí)行腳本,所以腳本本身不需要執(zhí)行權(quán)限。第二種執(zhí)行方法,本質(zhì)是腳本需要自己執(zhí)行,所以需要執(zhí)行權(quán)限。
- 第二個(gè)Shell腳本:多命令處理
# 在/home/xubh/目錄下創(chuàng)建一個(gè)banzhang.txt,在banzhang.txt文件中增加“I love cls”。
$ touch batch.sh
$ vi batch.sh
在batch.sh中輸入如下內(nèi)容
#!/bin/bash
cd /home/xubh
touch cls.txt
echo "I love cls" >>cls.txt
3. Shell中的變量
系統(tǒng)變量
- 常用系統(tǒng)變量
PWD、
USER等
- 案例實(shí)操
# 查看系統(tǒng)變量的值
$ echo $HOME
/home/xubh
# 顯示當(dāng)前Shell中所有變量:set
$ set
BASH=/bin/bash
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
自定義變量
-
基本語(yǔ)法
- 定義變量:變量=值
- 撤銷變量:unset 變量
- 聲明靜態(tài)變量:readonly變量,注意:不能unset
-
變量定義規(guī)則
- 變量名稱可以由字母、數(shù)字和下劃線組成,但是不能以數(shù)字開(kāi)頭,環(huán)境變量名建議大寫。
- 等號(hào)兩側(cè)不能有空格
- 在bash中,變量默認(rèn)類型都是字符串類型,無(wú)法直接進(jìn)行數(shù)值運(yùn)算。
- 變量的值如果有空格,需要使用雙引號(hào)或單引號(hào)括起來(lái)。
案例實(shí)操
# (1)定義變量A
$ A=5
$ echo $A
5
#(2)給變量A重新賦值
$ A=8
$ echo $A
8
#(3)撤銷變量A
$ unset A
$ echo $A
#(4)聲明靜態(tài)的變量B=2,不能unset
$ readonly B=2
$ echo $B
2
$ B=9
-bash: B: readonly variable
#(5)在bash中,變量默認(rèn)類型都是字符串類型,無(wú)法直接進(jìn)行數(shù)值運(yùn)算
$ C=1+2
$ echo $C
1+2
#(6)變量的值如果有空格,需要使用雙引號(hào)或單引號(hào)括起來(lái)
$ D=I love banzhang
-bash: world: command not found
$ D="I love banzhang"
$ echo $A
I love banzhang
#(7)可把變量提升為全局環(huán)境變量,可供其他Shell程序使用
$ vim helloworld.sh
在helloworld.sh文件中增加echo $B
#!/bin/bash
echo "helloworld"
echo $B
$ ./helloworld.sh
Helloworld
# 發(fā)現(xiàn)并沒(méi)有打印輸出變量B的值。
$ export B
$ ./helloworld.sh
helloworld
2
Array
像其它語(yǔ)言一樣,bash 也有數(shù)組類型。bash 中的數(shù)組是一個(gè)保存著很多值的變量,數(shù)組的長(zhǎng)度沒(méi)有限制,下標(biāo)也是從 0 開(kāi)始。在 bash 中有好幾種方法創(chuàng)建一個(gè)數(shù)組,如下所示。
Examples:
array[0] = val
array[1] = val
array[2] = val
array=([2]=val [0]=val [1]=val)
array=(val val val)
使用如下語(yǔ)法獲得數(shù)組特定位置的值:
${array[i]} # i是數(shù)組下標(biāo)
如果沒(méi)有指定數(shù)組下標(biāo),默認(rèn)返回第一個(gè)元素。想知道數(shù)組中有多少個(gè)元素,使用下面的語(yǔ)法:
${#array[@]}
Bash 也支持三元運(yùn)算符,如下面的例子所示:
${varname:-word} # 如果 varname 存在而且不為 null,返回它的值,否則返回 word
${varname:=word} # 如果 varname 存在而且不為 null,返回它的值,否則把word賦值給它并且返回 word
${varname:+word} # 如果 varname 存在而且不為 null,返回 word,否則返回 null
${varname:offset:length} # 它返回 $varname 的子字符串,從 offset 處開(kāi)始,長(zhǎng)度為 length
String Substitution
${variable#pattern} # 如果 pattern 匹配變量值的起始部分,刪除匹配 pattern 的最短的部分,然后返回剩余的
${variable##pattern} # 如果 pattern 匹配變量值的起始部分,刪除匹配 pattern 的最長(zhǎng)的部分,然后返回剩余的
${variable%pattern} # 如果 pattern 匹配變量值的結(jié)束部分,刪除匹配 pattern 的最短的部分,然后返回剩余的
${variable%%pattern} # 如果 pattern 匹配變量值的結(jié)束部分,刪除匹配 pattern 的最長(zhǎng)的部分,然后返回剩余的
${variable/pattern/string} # 把變量值中匹配 pattern 的最長(zhǎng)的部分替換為 string,只替換第一個(gè)匹配的部分
${variable//pattern/string} # 把變量值中匹配 pattern 的最長(zhǎng)的部分替換為 string,全局進(jìn)行替換
${#varname} # 返回變量值作為一個(gè)字符串的長(zhǎng)度
特殊變量:$n
- 基本語(yǔ)法
? 0代表該腳本名稱,
9代表第一到第九個(gè)參數(shù),十以上的參數(shù),十以上的參數(shù)需要用大括號(hào)包含,如${10})
-
案例實(shí)操
- 輸出該腳本文件名稱、輸入?yún)?shù)1和輸入?yún)?shù)2 的值
$ touch parameter.sh
$ vim parameter.sh
#!/bin/bash
echo "$0 $1 $2"
$ chmod 777 parameter.sh
$ ./parameter.sh cls xz
./parameter.sh cls xz
特殊變量:$#
- 基本語(yǔ)法
? $#(功能描述:獲取所有輸入?yún)?shù)個(gè)數(shù),常用于循環(huán))。
-
案例實(shí)操
- 獲取輸入?yún)?shù)的個(gè)數(shù)
$ vim parameter.sh
#!/bin/bash
echo "$0 $1 $2"
echo $#
$ chmod 777 parameter.sh
$ ./parameter.sh cls xz
parameter.sh cls xz
2
特殊變量:
@
- 基本語(yǔ)法
? *把所有的參數(shù)看成一個(gè)整體)
? @把每個(gè)參數(shù)區(qū)分對(duì)待)
-
案例實(shí)操
- 打印輸入的所有參數(shù)
$ vim parameter.sh
#!/bin/bash
echo "$0 $1 $2"
echo $#
echo $*
echo $@
$ bash parameter.sh 1 2 3
parameter.sh 1 2
3
1 2 3
1 2 3
特殊變量:$?
- 基本語(yǔ)法
$? (功能描述:最后一次執(zhí)行的命令的返回狀態(tài)。如果這個(gè)變量的值為0,證明上一個(gè)命令正確執(zhí)行;如果這個(gè)變量的值為非0(具體是哪個(gè)數(shù),由命令自己來(lái)決定),則證明上一個(gè)命令執(zhí)行不正確了。)
-
案例實(shí)操
- 判斷helloworld.sh腳本是否正確執(zhí)行
$ ./helloworld.sh
hello world
$ echo $?
0
4. 運(yùn)算符
-
基本語(yǔ)法
- “
[運(yùn)算式]”
- expr + , - , *, /, % 加,減,乘,除,取余
- “
- 注意:expr運(yùn)算符間要有空格
- 案例實(shí)操:
#(1)計(jì)算3+2的值
$ expr 2 + 3
5
#(2)計(jì)算3-2的值
$ expr 3 - 2
1
#(3)計(jì)算(2+3)X4的值
#(a)expr一步完成計(jì)算
$ expr `expr 2 + 3` \* 4
20
#(b)采用$[運(yùn)算式]方式
# S=$[(2+3)*4]
# echo $S
5. 條件判斷
- 基本語(yǔ)法
[ condition ](注意condition前后要有空格)
注意:條件非空即為true,[xubh]返回true,[] 返回false。
- 常用判斷條件
- 兩個(gè)整數(shù)之間比較
= 字符串比較
-lt 小于(less than) -le 小于等于(less equal)
-eq 等于(equal) -gt 大于(greater than)
-ge 大于等于(greater equal) -ne 不等于(Not equal)
- 按照文件權(quán)限進(jìn)行判斷
-r 有讀的權(quán)限(read)
-w 有寫的權(quán)限(write)
-x 有執(zhí)行的權(quán)限(execute)
- 按照文件類型進(jìn)行判斷
-f 文件存在并且是一個(gè)常規(guī)的文件(file)
-e 文件存在(existence)
-d 文件存在并是一個(gè)目錄(directory)
- 案例實(shí)操
#(1)23是否大于等于22
$ [ 23 -ge 22 ]
$ echo $?
0
#(2)helloworld.sh是否具有寫權(quán)限
$ [ -w helloworld.sh ]
$ echo $?
0
#(3)/home/xubh/cls.txt目錄中的文件是否存在
$ [ -e /home/xubh/cls.txt ]
$ echo $?
1
#(4)多條件判斷(&& 表示前一條命令執(zhí)行成功時(shí),才執(zhí)行后一條命令,|| 表示上一條命令執(zhí)行失敗后,才執(zhí)行下一條命令)
$ [ condition ] && echo OK || echo notok
OK
$ [ condition ] && [ ] || echo notok
notok
6. 流程控制
if 判斷
- 基本語(yǔ)法
if [expression]; then
will execute only if expression is true
else
will execute if expression is false
fi
? 注意事項(xiàng):
[ 條件判斷式 ],中括號(hào)和條件判斷式之間必須有空格
if后要有空格
-
案例實(shí)操
- 輸入一個(gè)數(shù)字,如果是1,則輸出banzhang zhen shuai,如果是2,則輸出cls zhen mei,如果是其它,什么也不輸出。
$ touch if.sh
$ vim if.sh
#!/bin/bash
if [ $1 -eq "1" ]
then
echo "banzhang zhen shuai"
elif [ $1 -eq "2" ]
then
echo "cls zhen mei"
fi
statement1 && statement2 # 兩個(gè)語(yǔ)句都為真
statement1 || statement2 # 至少一個(gè)語(yǔ)句為真
str1=str2 # str1 匹配 str2
str1!=str2 # str1 不匹配 str2
str1<str2 # str1 小于 str2
str1>str2 # str1 大于 str2
-n str1 # str1 不是 null (長(zhǎng)度大于 0)
-z str1 # str1 是 null (長(zhǎng)度為 0)
-a file # 文件存在
-d file # 文件存在而且是目錄
-e file # 文件存在,跟 -a 一樣
-f file # 文件存在,而且是常規(guī)文件(不是目錄或者其他特殊類型的文件)
-r file # 你有讀權(quán)限
-s file # 文件存在而且不為空
-w file # 你有寫權(quán)限
-x file # 你對(duì)文件有執(zhí)行權(quán)限,如果 file 是目錄的話,你對(duì)它有搜索權(quán)限
-N file # 從上次讀之后文件被修改過(guò)
-O file # 你是文件所有者
-G file # 文件的 group ID 跟你的 group ID (或之一,如果你在很多分組里)相同
file1 -nt file2 # file1 比 file2 更新
file1 -ot file2 # file1 比 file2 更老
-lt # 小于
-le # 小于等于
-eq # 等于
-ge # 大于等于
-gt # 大于
-ne # 不等于
$ chmod 777 if.sh
$ ./if.sh 1
banzhang zhen shuai
case 語(yǔ)句
- 基本語(yǔ)法
case $變量名 in
"值1")
? 如果變量的值等于值1,則執(zhí)行程序1
? ;;
"值2")
? 如果變量的值等于值2,則執(zhí)行程序2
? ;;
…省略其他分支…
*)
? 如果變量的值都不是以上的值,則執(zhí)行此程序
? ;;
esac
注意事項(xiàng):
- case行尾必須為單詞“in”,每一個(gè)模式匹配必須以右括號(hào)“)”結(jié)束。
- 雙分號(hào)“;;”表示命令序列結(jié)束,相當(dāng)于java中的break。
- 最后的“*)”表示默認(rèn)模式,相當(dāng)于java中的default。
-
案例實(shí)操
- 輸入一個(gè)數(shù)字,如果是1,則輸出banzhang,如果是2,則輸出cls,如果是其它,輸出renyao。
$ touch case.sh
$ vim case.sh
!/bin/bash
case $1 in
"1")
echo "banzhang"
;;
"2")
echo "cls"
;;
*)
echo "renyao"
;;
esac
$ chmod 777 case.sh
$ ./case.sh 1
1
for 循環(huán)
-
基本語(yǔ)法1
for (( initialisation ; ending condition ; update ))
do
statements...
done
```
-
案例實(shí)操
- 從1加到100
$ touch for1.sh
$ vim for1.sh
#!/bin/bash
s=0
for((i=0;i<=100;i++))
do
s=$[$s+$i]
done
echo $s
$ chmod 777 for1.sh
$ ./for1.sh
“5050”
- 基本語(yǔ)法2
for name [in list]
do
statements that can use $name
done
- 案例實(shí)操
- 打印所有輸入?yún)?shù)
$ touch for2.sh
$ vim for2.sh
#!/bin/bash
#打印數(shù)字
for i in $*
do
echo "ban zhang love $i "
done
$ chmod 777 for2.sh
$ bash for2.sh cls xz bd
ban zhang love cls
ban zhang love xz
ban zhang love bd
- 比較
@區(qū)別
(a)@都表示傳遞給函數(shù)或腳本的所有參數(shù),不被雙引號(hào)“”包含時(shí),都以
2 …$n的形式輸出所有參數(shù)。
$ touch for.sh
$ vim for.sh
#!/bin/bash
for i in $*
do
echo "ban zhang love $i "
done
for j in $@
do
echo "ban zhang love $j"
done
$ bash for.sh cls xz bd
ban zhang love cls
ban zhang love xz
ban zhang love bd
ban zhang love cls
ban zhang love xz
ban zhang love bd
(b)當(dāng)它們被雙引號(hào)“”包含時(shí),“1
n”的形式輸出所有參數(shù);“
1” “
n”的形式輸出所有參數(shù)。
$ vim for.sh
#!/bin/bash
for i in "$*"
#$*中的所有參數(shù)看成是一個(gè)整體,所以這個(gè)for循環(huán)只會(huì)循環(huán)一次
do
echo "ban zhang love $i"
done
for j in "$@"
#$@中的每個(gè)參數(shù)都看成是獨(dú)立的,所以“$@”中有幾個(gè)參數(shù),就會(huì)循環(huán)幾次
do
echo "ban zhang love $j"
done
$ chmod 777 for.sh
$ bash for.sh cls xz bd
ban zhang love cls xz bd
ban zhang love cls
ban zhang love xz
ban zhang love bd
while 循環(huán)
- 基本語(yǔ)法
while condition; do
statements
done
- 案例實(shí)操
- 從1加到100
$ touch while.sh
$ vim while.sh
#!/bin/bash
s=0
i=1
while [ $i -le 100 ]
do
s=$[$s+$i]
i=$[$i+1]
done
echo $s
$ chmod 777 while.sh
$ ./while.sh
5050
7. read讀取控制臺(tái)輸入
- 基本語(yǔ)法
? read(選項(xiàng))(參數(shù))
? 選項(xiàng):
-p:指定讀取值時(shí)的提示符;
-t:指定讀取值時(shí)等待的時(shí)間(秒)。
參數(shù)
? 變量:指定讀取值的變量名
- 案例實(shí)操
? (1)提示7秒內(nèi),讀取控制臺(tái)輸入的名稱
$ touch read.sh
$ vim read.sh
#!/bin/bash
read -t 7 -p "Enter your name in 7 seconds " NAME
echo $NAME
$ ./read.sh
Enter your name in 7 seconds xiaoze
xiaoze
8. 函數(shù)
系統(tǒng)函數(shù)
- basename基本語(yǔ)法
basename [string / pathname] [suffix] (功能描述:basename命令會(huì)刪掉所有的前綴包括最后一個(gè)(‘/’)字符,然后將字符串顯示出來(lái)。
選項(xiàng):
suffix為后綴,如果suffix被指定了,basename會(huì)將pathname或string中的suffix去掉。
- 案例實(shí)操
- 截取該/home/xubh/banzhang.txt路徑的文件名稱
$ basename /home/xubh/banzhang.txt
banzhang.txt
$ basename /home/xubh/banzhang.txt .txt
banzhang
- dirname基本語(yǔ)法
? dirname 文件絕對(duì)路徑(功能描述:從給定的包含絕對(duì)路徑的文件名中去除文件名(非目錄的部分),然后返回剩下的路徑(目錄的部分))
-
案例實(shí)操
- 獲取banzhang.txt文件的路徑
$ dirname /home/xubh/banzhang.txt
/home/xubh
自定義函數(shù)
- 基本語(yǔ)法
[ function ] funname[()]
{
? Action;
? [return int;]
}
funname
-
經(jīng)驗(yàn)技巧
? 1.必須在調(diào)用函數(shù)地方之前,先聲明函數(shù),shell腳本是逐行運(yùn)行。不會(huì)像其它語(yǔ)言一樣先編譯。
? 2.函數(shù)返回值,只能通過(guò)$?系統(tǒng)變量獲得,可以顯示加:return返回,如果不加,將以最后一條命令運(yùn)行結(jié)果,作為返回值。return后跟數(shù)值n(0-255)
-
案例實(shí)操
計(jì)算兩個(gè)輸入?yún)?shù)的和
$ touch fun.sh
$ vim fun.sh
#!/bin/bash
function sum()
{
s=0
s=$[ $1 + $2 ]
echo "$s"
}
read -p "Please input the number1: " n1;
read -p "Please input the number2: " n2;
sum $n1 $n2;
$ chmod 777 fun.sh
$ ./fun.sh
Please input the number1: 2
Please input the number2: 5
7