【归档】[OS] Shell脚本


Unit: 3.5
Link: https://lgwain.gitbooks.io/os/unit35.html
HomeWork: https://lgwain.gitbooks.io/os/lx3b.html

Shell脚本是什么?

通俗的解释就是一堆Linux命令的逻辑化处理。

为什么要编写Shell脚本?

在做开发的时候,有的时候需要部署环境或者是打包发布,往往都需要在终端里敲好多的命令才能做一件事,但是如果每次部署都要敲一堆命令,那么效率是非常低的,也会使人感到烦躁。所以,我们可以编写Shell脚本,将要执行的命令写在一起,用的时候只需要运行一下脚本就一切都搞定了。

从第一行开始!

为了确保Shell脚本可以正常运行,请将下面一行代码写在Shell脚本的第一行:

#!/bin/bash

确保了脚本总是运行在bash中。

如何执行Shell脚本?

首先我们先新建一个简单的Shell脚本,让它输出 Hello World!

$ touch t.sh
$ vi t.sh
# Coding...
$ cat t.sh
#!/bin/bash
echo Hello World!

(一)使用 bash ScriptName 执行Shell脚本:只需要对脚本有读的权限(chmod 444 ./t.sh

$ bash t.sh 
Hello World!

(二)像运行命令一样 ./ScriptName 执行Shell脚本:需要对脚本有执行权限(chmod 555 ./t.sh

$ ./t.sh
Hello World!

(三)使用命令 source ScriptName 运行Shell脚本:同样要对脚本有执行权限

和前两种执行方式不同的是,前两种方式是在当前Shell中创建了一个子进程来执行相应的脚本,不会对父进程有影响,而命令 source 会在当前的Shell中执行相应的脚本,直接影响当前的进程。

$ source t.sh
Hello World!

只输出 Hello World! 看不出来效果,我们在脚本文件中加入一行切换目录的命令:

#!/bin/bash
cd ../
echo Hello World!

分别使用第二种和第三种方式执行,看效果:

$ pwd
/Users/yuchunyu97/Projects/www/Homework/os04/src/script
# 第二种
$ ./t.sh 
Hello World!
$ pwd
/Users/yuchunyu97/Projects/www/Homework/os04/src/script
# 第三种
$ source t.sh 
Hello World!
$ pwd
/Users/yuchunyu97/Projects/www/Homework/os04/src

pwd 命令可以显示当前所在的目录。

可以看出来第二种方式执行切换目录的命令并没有对当前的目录产生影响,而第三种方式使当前目录返回了上一级目录。

在终端输出 echo 、读取用户输入 read

# echo 命令介绍

$ cat t.sh 
#!/bin/bash
# 输出字符串
echo "Hello World"
# 输出字符串也可以不加双引号
echo Hello World
# 输出双引号 "
echo \"Hello World\"
# echo命令默认换行,使用 -n 可以设置不换行
echo -n Please Input Something: 
# 读取用户输入,并存入变量
read line
# 输出存在变量里的字符串
echo "Get It: $line"
# 使用单引号 ' 可以将变量输出成字符串
echo 'It is not a variable $line'
# 使用反引号 ` 执行命令
echo Current Time: `date`
# 使用大于号 > 将输出重定向到文件
echo This line is in a file > t.tmp

$ ./t.sh 
Hello World
Hello World
"Hello World"
Please Input Something:Hi Shell Script
Get It: Hi Shell Script
It is not a variable $line
Current Time: 2017年11月 3日 星期五 15时33分52秒 CST

$ ls
t.sh  t.tmp

$ cat t.tmp 
This line is in a file

关于 echo 的详细介绍:Shell命令:echo 命令详解

# read 命令介绍

$ cat t.sh
#!/bin/bash
# -p 显示提示信息,并且不换行
# 可以同时接受多个值,以空格分隔
read -p "Enter your name and age separated by Space: " name age
echo "Hi, $name. Your age is $age"
# -t 限制用户的输入时间
read -t 5 -p "You have 5 Seconds to input: " line
echo -e "\nYour input is: $line"
# -s 可以不显示用户的输入
read -s -p "Enter Password: " passwd
echo -e "\nYour password is: $passwd"

$ ./t.sh 
Enter your name and age separated by Space: Yuchunyu 20
Hi, Yuchunyu. Your age is 20
You have 5 Seconds to input: 
Your input is: 
Enter Password: 
Your password is: MyPassword

测试/判断命令 test

在Linux中执行判断时,如果正确则返回 0 ,如果错误则返回 1

$? 临时存储当前判断的结果。

语法:

test expression  or [ expression ] or [[ expression ]]

使用表达式来测试文件状态:

-f <file>        是否为文件
-d <file>        是否为目录
-r <file>        是否有读权限
-w <file>        是否有写权限
-x <file>        是否有执行权限
-s <file>        是否有非零大小

例:

$ chmod 444 t.tmp
$ ls -l t.tmp
-r--r--r--  1 yuchunyu97  staff  23 11  3 15:39 t.tmp
$ cat t.sh 
#!/bin/bash
test -f t.tmp
echo Is an ordinary file? $?
test -d t.tmp
echo Is a directory? $?
test -r t.tmp
echo Is Readable? $?
test -w t.tmp
echo Is Writable? $?
test -x t.tmp
echo Is Executable? $?
test -s t.tmp
echo Has Non-Zero Length? $?

$ ./t.sh 
Is an ordinary file? 0
Is a directory? 1
Is Readable? 0
Is Writable? 1
Is Executable? 1
Has Non-Zero Length? 0

# 0 表示有
# 1 表示无

字符串测试:

-n <string>        字符串是否不为空
-z <string>        字符串是否为空
<string> == <string>    字符串是否相等
<string> != <string>    字符串是否不相等

例:

$ cat t.sh 
#!/bin/bash
test -n ""
echo Empty String is not empty? $?
test -z ""
echo Empty String is empty? $?
test "str" == "str1"
echo \"str\" and \"str1\" are equal? $?
test "str" != "str1"
echo \"str\" and \"str1\" are not equal? $?

$ ./t.sh 
Empty String is not empty? 1
Empty String is empty? 0
"str" and "str1" are equal? 1
"str" and "str1" are not equal? 0

算数测试:

<value> -eq <value>    是否相等
<value> -ne <value>    是否不相等
<value> -lt <value>    是否小于
<value> -le <value>    是否小于等于
<value> -gt <value>    是否大于
<value> -ge <value>    是否大于等于

例:

$ cat t.sh 
#!/bin/bash
test 1 -eq 2
echo 1 equals 2? $?
test 1 -ne 2
echo 1 not equals 2? $?
test 7 -lt 7
echo 7 less than 7? $?
test 7 -le 7
echo 7 less than or equal 7? $?
test 7 -gt 6
echo 7 greater than 6? $?
test 7 -ge 6
echo 7 greater than or equal 6? $?

$ ./t.sh 
1 equals 2? 1
1 not equals 2? 0
7 less than 7? 1
7 less than or equal 7? 0
7 greater than 6? 0
7 greater than or equal 6? 0

&& 和 ||

可以用于有条件的执行命令。

command1 && command2
如果command1成立,再执行command2

command1 || command2
如果command1不成立,再执行command2

例:

# 查看当前目录,有文件 t.tmp
$ ls
t.sh  t.tmp
# 如果有 t.tmp,就删除
# 如果没有 e.file,就新建一个 e.file
$ cat t.sh 
#!/bin/bash
(test -f t.tmp) && rm -f t.tmp
(test -f e.file) || touch e.file
# 执行脚本
$ ./t.sh
# 查看当前目录, t.tmp被删除了,新建了一个 e.file
$ ls
e.file t.sh

if 命令

语法:

if [ status(true) ]
then
	process
elif [ status(true) ]
then
	process
else
	process
fi

注: ifelif 后面的空格不能省略,还有后面的 [ status ] 中,status两边的空格也不能省略。别忘了在最后加 fi

例:

$ cat t.sh 
#!/bin/bash
read -p "Please input a number: " num
if [ $num -lt 10 ]
then
	echo $num is less than 10
elif [ $num -gt 10 ]
then
	echo $num is greater than 10
else
	echo $num is equal to 10
fi

$ ./t.sh 
Please input a number: 2
2 is less than 10
$ ./t.sh
Please input a number: 12
12 is greater than 10
$ ./t.sh
Please input a number: 10
10 is equal to 10

case 命令

语法:

case $var in  
pattern1)  command1 ;;  
pattern2)  command2 ;;  
       *)  command3 ;;
esac  

注:每一个 pattern 后面有两个分号 ;; ,最后要加 esac

例:

$ cat t.sh 
#!/bin/bash
read -p "Please input \"yes\" or \"no\": " var
case $var in
	[Yy][Ee][Ss])
		echo Your input is YES;;
	[Nn][Oo])
		echo Your input is NO;;
	*)
		echo Input Error;;
esac

$ ./t.sh 
Please input "yes" or "no": Yes
Your input is YES
$ ./t.sh
Please input "yes" or "no": no
Your input is NO
$ ./t.sh
Please input "yes" or "no": hello
Input Error

while 命令

语法:

while staues(true)
do
commands

[break]
[continue]

done

例:

$ cat t.sh 
#!/bin/bash
guess=37
while true
do
	read -p "Please input a number to guess: " num
	if [ $num -eq $guess ]
	then
		echo Bingo! It\'s $num
		break
	elif [ $num -lt $guess ]
	then
		echo Please guess a bigger number.
		continue
	elif [ $num -gt $guess ]
	then
		echo Please guess a smaller number.
		continue
	fi
done

$ ./t.sh  
Please input a number to guess: 30
Please guess a bigger number.
Please input a number to guess: 40
Please guess a smaller number.
Please input a number to guess: 35
Please guess a bigger number.
Please input a number to guess: 37
Bingo! It's 37

注:Shell脚本中给变量赋值时,等号 = 两边不能有空格。

for 命令

语法:

for identifier in list
do
commands to be executed on $identifier
done

例:

$ cat t.sh 
#!/bin/bash
for i in {1..10}
do
	echo $i
done
$ ./t.sh 
1
2
3
4
5
6
7
8
9
10

$ cat t.sh
#!/bin/bash
for i in 1 2 3 0 6
do
	echo $i
done
$ ./t.sh  
1
2
3
0
6

$ cat t.sh
#!/bin/bash
for i in cat dog pig
do
	echo $i
done
$ ./t.sh  
cat
dog
pig

$ cat t.sh 
#!/bin/bash
for i in `ls ../`
do
	echo $i
done
$ ./t.sh 
a.out
script
sh.c

Shell脚本的参数

在命令行上的参数传递给Shell脚本,被存在了特殊的变量里。

语法:

$1, $2, $3 ... 依次代表传给Shell脚本的参数
$@ 代表 "$1" "$2" "$3"
$* 代表 "$1 $2 $3"
$# 储存参数的个数

例:

$ cat t.sh 
#!/bin/bash
echo First parameter: $1
echo Second parameter: $2
echo Number of parameters: $#
echo $@
echo $*

$ ./t.sh one two three four five
First parameter: one
Second parameter: two
Number of parameters: 5
one two three four five
one two three four five

shift 命令:位置参数可以用 shift 命令左移。比如 shift 3 表示原来的 $4 现在变成 $1 ,原来的 $5 现在变成 $2 等等,原来的 $1$2$3 丢弃, $0 不移动。不带参数的 shift 命令相当于 shift 1

例:

$ cat t.sh 
#!/bin/bash
while [ $# -gt 0 ]
do
	echo 第一个参数为:$1
	shift
done
$ ./t.sh 1 2 3 4 5
第一个参数为:1
第一个参数为:2
第一个参数为:3
第一个参数为:4
第一个参数为:5

这个命令可以让我们逐个的处理命令行参数。

算数相关的命令

可以使用 let 或者 $(( expr )) 来执行算数运算。

例:

$ cat t.sh 
#!/bin/bash
let x=7+8
echo $x
echo $(( (6 + 8)*9 ))
$ ./t.sh 
15
126

也可以使用命令 expr 。不过这个比前两个慢很多。注意使用 ()* 的时候需要转义。

$ echo `expr 3 + 5`
8
$ expr 3 * ( 3 + 5 )
zsh: unknown file attribute: 
# ( 、)、* 需要转义
$ expr 3 \* \( 3 + 5 \)
24

函数

语法:

function func_name() {
    statements
    [return]
}

例:

$ cat t.sh 
#!/bin/bash
function show() {
    echo "hello , $1"
}
show world
$ ./t.sh 
hello , world
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章