0%

Shell笔记

Unix Shells

  • Bourne shell(sh)
  • C shell(csh)
  • Korn shell(ksh)
  • Restricted shell
  • TC shell(tcsh)

Linux Shells

  • Bourne again shell(bash)
  • A shell(ash)

运行脚本

在第一行加入

1
2
3
#!/bin/bash

#!/bin/sh

1
. + 空格 + 文件名

(不需要权限)

1
. + 路径

(需要权限)

1
/bin/bash + 文件名

变量

定义变量

1
2
a=3
b="haha"

注意

  • 变量名和等号之间不能有空格!
  • 不能用关键词,首字符不能为数字,可以使用下划线

使用变量

在定义过的变量前加上$
可以用{}将变量名括起来,这个是可选的,但是有时候输出必须要区分开

只读变量

1
2
3
4
readonly var=3

var=3
readonly var

变量类型

局部变量
局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。

环境变量
所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。

shell变量
shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行

特殊变量

变量 描述
$0 当前脚本文件名
$n 传递给脚本或函数的参数,n是一个数字,表示第几个参数,第一个参数$1
$# 传递给脚本或函数的参数个数
$* 传递给脚本或函数的所有参数
$@ 传递给脚本或函数的所有参数,被双引号包含时,与$*稍有不同
$? 上个命令的退出状态或函数的返回值
$$ 当前Shell进程ID
$! 后台运行的最后一个进程的ID号
$- 显示Shell使用的当前选项,与set命令功能相同。

$*$@的区别
$*$@ 都表示传递给函数或脚本的所有参数,不被双引号(“ “)包含时,都以"$1" "$2" … "$n" 的形式输出所有参数。但是当它们被双引号(“ “)包含时,"$*" 会将所有的参数作为一个整体,以
"$1 $2 … $n"的形式输出所有参数;"$@" 会将各个参数分开,以"$1" "$2" … "$n"的形式输出所有参数。

$?
可以获取上一个命令的退出状态。所谓退出状态,就是上一个命令执行后的返回结果。退出状态是一个数字,一般情况下,大部分命令执行成功会返回 0,失败返回 1。

删除变量

1
unset a

Shell字符串

单引号
原样输出,不进行转义

双引号
可以有变量和转义字符

获取字符串长度

1
2
str="abcd"
echo ${#str}

提取子字符串

1
2
str="abcd"
echo ${#str:2:3} #bc

查找子字符串

查找字符 i 或 o 的位置(哪个字母先出现就计算哪个):

1
2
string="runoob is a great site"
echo `expr index "$string" io` # 输出 4

数组

定义数组

1
2
3
4
5
6
7
8
9
10
11
12
13
数组名=(值1 值2 ... 值n)
array_name=(value0 value1 value2 value3)

array_name=(
value0
value1
value2
value3
)

array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen

可以不使用连续的下标,而且下标的范围没有限制。

读取数组

1
${数组名[下标]}

获取数组长度

1
2
3
4
5
6
# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
lengthn=${#array_name[n]}

注释

用#开头
若大量代码需要注释,那么可以有定义成函数并不调用

多行注释

1
2
3
4
5
:<<EOF
注释内容...
注释内容...
注释内容...
EOF

EOF 也可以使用其他符号:

1
2
3
4
5
6
7
8
9
10
11
:<<'
注释内容...
注释内容...
注释内容...
'

:<<!
注释内容...
注释内容...
注释内容...
!

Shell基本运算符

原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。
expr 是一款表达式计算工具,使用它能完成表达式的求值操作。

算术运算符

下表列出了常用的算术运算符,假定变量 a 为 10,变量 b 为 20:

运算符 说明 举例
+ 加法 expr $a + $b 结果为 30。
- 减法 expr $a - $b 结果为 -10。
* 乘法 expr $a \* $b 结果为 200。
/ 除法 expr $b / $a 结果为 2。
% 取余 expr $b % $a 结果为 0。
= 赋值 a=$b 将把变量 b 的值赋给 a。
== 相等 用于比较两个数字,相同则返回 true。[ $a == $b ] 返回 false。
!= 不相等 用于比较两个数字,不相同则返回 true。[ $a != $b ] 返回 true。

注意:条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 [ $a == $b ]。

乘号(*)前边必须加反斜杠(\)才能实现乘法运算;

运算

expr函数

$(())可以转化为表达式

小数运算

awk 比较复杂…

1
2
echo `awk 'BRGIN{a=5.5/3.3;print a}'`
echo `awk -v x=2.45 -v y=3.123 'BEGIN{printf "%.2f\n",x*y}'`

| bc

1
2
s2=$(echo "scale=3; 6 / 5"  | bc)
echo $s2

关系运算符

符号 描述
-eq 等于
-ne 不等
-gt 大于
-lt 小于
-ge 大于等于
-le 小于等于

布尔运算符

符号 描述
-o
-a

逻辑运算符

符号 描述
||
&&

字符串运算符

比较的时候等号两边要加空格…

符号 描述
= 相等
!= 不等
-z 长度是否为0
-n 长度是否不为0
string 是否为空

文件测试运算符

符号 描述
-b file 检测文件是否是块设备文件
-c file 检测文件是否是字符设备文件
-d file 检测文件是否是目录
-f file 检测文件是否是普通文件(既不是目录,也不是设备文件)
-g file 检测文件是否设置了 SGID 位
-k file 检测文件是否设置了粘着位(Sticky Bit)
-p file 检测文件是否是有名管道
-u file 检测文件是否设置了 SUID 位
-r file 检测文件是否可读
-w file 检测文件是否可写
-x file 检测文件是否可执行
-s file 检测文件是否为空(文件大小是否大于0)
-e file 检测文件(包括目录)是否存在

输出

echo
单引号不转义,双引号转义,-e开启转义

printf
格式化输出

test命令

用于检测某条件是否成立
代码中[]执行基本的算术运算

流程控制

条件控制

if

1
2
3
4
5
6
7
8
9
10
11
if condition
then
command1
command2
...
commandN
fi



if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi

if-else

1
2
3
4
5
6
7
8
9
if condition
then
command1
command2
...
commandN
else
command
fi

if-else-if-else

1
2
3
4
5
6
7
8
9
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi

循环

for

1
2
3
4
5
6
7
8
9
10
11
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done



for var in item1 item2 ... itemN; do command1; command2… done;

计数循环

1
2
{0..9}
$(seq 10)

while

1
2
3
4
while condition
do
command
done

计数循环

1
2
3
4
5
6
7
#!/bin/bash
int=1
while(( $int<=5 ))
do
echo $int
let "int++"
done

until

直到条件满足截止

1
2
3
4
until condition
do
command
done

分支

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
case 值 in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
*) #其他
;;
esac

Eg.

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
while :
do
echo -n "输入 1 到 5 之间的数字:"
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
break
;;
esac
done

跳出循环

break

continue

函数

1
2
3
4
5
6
7
8
9
[ function ] funname [()]

{

action;

[return int;]

}

可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255)
函数返回值在调用该函数后通过 $? 来获得。
必须使用前定义
在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数…
参数总数 $#
作为一个字符串输出所有参数 $*

参数处理 说明
$# 传递到脚本的参数个数
$* 以一个单字符串显示所有向脚本传递的参数
$$$$ 脚本运行的当前进程ID号
$! 后台运行的最后一个进程的ID号
$@ $*相同,但是使用时加引号,并在引号中返回每个参数。
$- 显示Shell使用的当前选项,与set命令功能相同。
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

输入输出重定向

命令 说明
command > file 将输出重定向到 file。
command < file 将输入重定向到 file。
command >> file 将输出以追加的方式重定向到 file。
n > file 将文件描述符为 n 的文件重定向到 file。
n >> file 将文件描述符为 n 的文件以追加的方式重定向到 file。
n >& m 将输出文件 m 和 n 合并。
n <& m 将输入文件 m 和 n 合并。
<< tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入。

Here Document
Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。

它的基本的形式如下:

1
2
3
command << delimiter
document
delimiter

它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。

/dev/null 文件
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null

1
$ command > /dev/null

/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null文件非常有用,将命令的输出重定向到它,会起到”禁止输出”的效果。

如果希望屏蔽 stdout 和 stderr,可以这样写:

1
$ command > /dev/null 2>&1

Shell 文件包含

和其他语言一样,Shell 也可以包含外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。

Shell 文件包含的语法格式如下:

1
2
3
. filename   # 注意点号(.)和文件名中间有一空格

source filename

Have fun.