YOU'VE MADE A BRAVE DECISION, WELCOME.

每一个不曾起舞的日子都是对生命的辜负。

学习笔记:Shell

Shell与Shell语言

Shell是一种编程语言,但是sh/bash/csh/zsh/…它们也叫Shell,实际上这里的Shell是一种应用程序,它负责解释执行编写的Shell脚本。

Shell脚本

1
2
#! /bin/sh
echo "hello shell!"

第一行的#!是一个约定标记,它告诉脚本这段脚本需要什么解释器来执行。第二行的echo命令则负责向屏幕上输出一句话。

运行方式

运行shell程序有3种方法:

  1. chmod +x使文件具有可执行权限, 直接运行;
  2. 直接调用解释器, 将脚本文件作为参数传入 (比如bash hi.sh);
  3. 使用source(也可用 . 代替)执行文件。

通常情况下,最方便的方式就是方式1,通过方式1执行你需要在脚本第一行写好这段脚本由哪个解释器来解释,除此之外方式1与方式2执行命令就没有区别了,但方式3执行的方式与前两种都不同:使用source执行shell脚本时, 不会创建子进程, 而是在父进程中直接执行!

变量

和其它语言一样Shell中也有变量,而且更简单,但有一些比较特殊的地方。

  1. Shell中的变量只有字符串这一种类型;
  2. Shell中变量名与变量值没有长度限制;
  3. Shell的变量也允许比较操作和整数操作,只要变量中的字符串为数字。

定义变量

1
2
3
PS:= 两边不能加空格, 当赋值语句包含空格时请加引号(单引号/双引号均可)
variable_name="ghui's blog"

Shell中的变量可以分为 两种 类型:

  1. 局部变量 (定义变量时在前面加local修饰符)
  2. 全局变量 (定义变量时不加任何修饰符)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
局部变量的可见范围是代码块或函数内,全局变量在全局范围内可见,例子:
#! /bin/sh
num=111 #全局变量
func1()
{
local num=222 #局部变量
echo $num
}
echo "before---$num"
func1
echo "after---$num"
输出:
before---111
222
after---111

使用变量

使用一个定义过的变量,只要在变量名前面加$即可,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
name=ghui
echo $name
echo ${name}
PS:#{} 为了帮助解释器识别变量边界, 非必须
注意:被双引号括起来的变量会发生变量替换, 单引号不会,例子:
#! /bin/sh
str='abc'
echo "1 print $str"
echo '2 print $str'
输出:
1 print abc
2 print $str

注释

Shell中注释使用#,而且它不支持多行注释。

字符串操作

字符串拼接

1
2
3
4
name="shell"
sayHi="hello, "$name" !"
sayHi2="hello, ${name} !"
echo $sayHi $sayHi2

字符串长度

1
2
3
4
5
string="abcd"
echo ${#string}
输出:
4

截取字符串

1
2
3
4
5
6
7
str="hello shell"
echo ${str:2}
echo ${string:1:3}
输出:
llo shell
ell

流程控制

if/else

1
2
3
4
5
6
7
8
9
10
11
12
if condition
then
do something
elif condition
then
do something
elif condition
then
do something
else
do something
fi
1
2
3
4
5
6
7
8
9
10
11
12
#! /bin/sh
a=1
if [ $1=$a ]
then
echo "you input 1"
elif [ $1=2 ]
then
echo "you input 2"
else
#do nothing
echo " you input $1"
fi

注意:

  • 如果某个条件下的执行体为空,不能写这个条件
  • [ ] 两边一定要加空格

switch

1
2
3
4
5
6
7
8
9
10
基本结构:
case expression in
pattern1)
do something... ;;
pattern2)
do something... ;;
pattern2)
do something... ;;
...
esac
1
2
3
4
5
6
7
8
9
10
11
12
13
#! /bin/sh
input=$1
case $input in
1 | 0)
str="一or零";;
2)
str="二";;
3)
str="三";;
*)
str=$input;;
esac
echo "---$str"

这个例子会根据你执行此脚本时传入的参数不同在屏幕上输出不同的值,其中第一个case 1 | 0代表逻辑或。

  • ;;相当于其它语言中的break
  • 每个pattern之后记得加)
  • 最后记得加esac (反的case)

循环

for循环

1
2
3
4
5
6
7
基本结构:
for name [in list]
do
...
done
PS:[]括起来的 in list 为可选部分,如果省略in list则默认为in "$@",即你执行此命令时传入的参数列表。
1
2
3
4
5
遍历当前目录下的所有txt文件,并依次打开。例子:
for file in *.txt
do
open $file
done

while循环

1
2
3
4
5
基本结构:
while condition
do
do something
done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#! /bin/sh
i=0
while ((i<5));
do
((i++))
echo "i=$i"
done
输出:
i=1
i=2
i=3
i=4
i=5

函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
方式一:
function funcname()
{
do something
}
方式二:
funcname ()
{
do something
}
例子:
#! /bin/sh
# ad.sh 计算sum
add()
{
let "sum=$1+$2"
return $sum
}
add $1 $2
echo "sum=$?"
输入:
ad 1 2
输出:
sum=3

向脚本传参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#! /bin/sh
# test.sh
echo "$# parameters";
echo "$@";
echo "$0"
echo "$1"
输入:
test.sh 11 22
输出:
2 parameters
11 22
test.sh
11