一、Shell简介
Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。
Shell 编程跟 JavaScript、php 编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。
实例如下:
#!/bin/bash
echo "Hello World !"
#! 告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序
二、Shell变量
定义变量
your_name="runoob.com"
(1)等号与左右两边不能有空格;
(2)定义变量时不加$符号;
使用变量
your_name="qinjx"
echo $your_name
your_name="alibaba"
echo ${your_name}
readonly your_name
unset your_name
(1)变量名外面的花括号是可选的,推荐给所有变量加上花括号;
(2)已定义的变量,可以被重新定义;
(3)通过readonly
可以定义只读变量 ;
(4)通过unset
可以删除变量;
变量的类型
运行shell时,会同时存在三种变量:局部变量、环境变量、shell变量。
三、Shell 字符串
字符串使用时,可以用单引号,也可以用双引号。单引号与双引号的区别:
(1)单引号里的任何字符都会原样输出,单引号字符串中的变量引用是无效的;
(2)单引号只能成对出现,不能单独出现(对单引号使用转义符后也不行);
(3)双引号中可以对变量 进行引用${your_name}
;
(4)双引号中可以对字符进行转义\n
;
补充:echo -e "hello world\n"
—echo -e表示开启转义
str='this is a string'
your_name='runoob'
str="Hello, I know you are \"${your_name}\"! "
拼接字符串
单引号、双引号均可用来拼接字符串
your_name="shell"
greeting_0="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting_0 $greeting_1 #输出:hello, shell ! hello, shell !
greeting_2='hello, '$your_name' !'
greeting_3='hello, ${your_name} !'
echo $greeting_2 $greeting_3 #输出:hello, shell ! hello, ${your_name} !
获取字符串长度
string="abcd"
echo ${#string} #输出 4
提取子字符串
以下实例从字符串第 1个字符(从0开始记)开始截取 4 个字符:
string="shell is a great site"
echo ${string:1:4} # 输出 hell
查找子字符串
查找字符 i 或 o 的位置(哪个字母先出现就计算哪个):
string="runoob is a great site"
echo `expr index "$string" io` # 输出 4
四、Shell 数组
说明
(1)bash支持一维数组(不支持多维数组),并且没有限定数组的大小。
(2)数组元素的下标由 0 开始编号。初始化时不需要定义数组大小。
(3)获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0。
定义数组
定义数组的一般形式如下:
(1)数组名=(值1 值2 … 值n)
array_name1=(value0 value1 value2 value3)
array_name2=(
value0
value1
value2
value3
)
(2)单独定义数组的各个分量(可以不使用连续的下标):
array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen
读取数组
(1)读取数组元素值的一般格式为: ${数组名[下标]};
(2)使用 @或* 符号可以获取数组中的所有元素;
valuen=${array_name[n]}
echo ${array_name[@]}
echo ${array_name[*]}
获取数组的长度
获取数组长度的方法与获取字符串长度的方法相同。
length=${#array_name[@]} #获取数组中非空元素(长度在于0的元素)的个数
length=${#array_name[*]} #同上
length_n=${#array_name[n]} #获取数组中第n个元素的长度
五、Shell 注释
以 # 开头的行就是注释,会被解释器忽略。那么如何实现多行注释呢?
(1)通过每一行加一个 # 号可达到多行注释的效果,但不太方便。
(2)可以把这一段要注释的代码用一对花括号括起来,定义成一个函数,没有地方调用这个函数,这块代码就不会执行,达到了和注释一样的效果。
(3)多行注释还可以使用以下格式:
:<<MYFLAG
注释内容...
注释内容...
注释内容...
MYFLAG
六、Shell 参数传递
我们可以在执行 Shell 脚本时,向脚本传递参数。脚本内获取参数的格式为:$n。n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……
./myshell.sh P1 P2 P3
向脚本传入了4个参数。
#!/bin/bash
echo ${0} #`./myshell.sh
echo ${1} #P1
echo ${2} #P2
echo ${3} #P3
echo $* #"P1 P2 P3"
echo $@ #"P1" "P2" "P3"
参数处理 | 说明 |
---|---|
$# | 传递到脚本(或函数)的参数个数 |
$* | 返回所有参数,并将其合并成一个字符串 |
$$ | 脚本运行的当前进程ID号 |
$! | 后台运行的最后一个进程的ID号 |
$@ | 返回所有参数,并将其组成一个字符串数组 |
$? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。 |
七、Shell 运算符
算数运算符
运算符 | 说明 | 举例 |
---|---|---|
+ | 加法 | 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。 |
Shell 里面的中括号(包括单中括号与双中括号)可用于一些条件的测试,常可代替test
命令:
-
算术比较, 比如一个变量是否为0,
[ $var -eq 0 ]
。 -
文件属性测试,比如一个文件是否存在,
[ -e $var ]
, 是否是目录,[ -d $var ]
。 -
字符串比较, 比如两个字符串是否相同,
[[ $var1 = $var2 ]]
。
注意:(1)条件表达式要放在方括号之间,并且要有空格,例如: [
a
=
=
a==
a==b] 是错误的,必须写成 [ $a == $b ]。
(2)表达式和运算符之间要有空格,例如 2+2
是不对的,必须写成 2 + 2
。
关系运算符
关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
运算符 | 说明 | 举例 |
---|---|---|
-eq | 检测两个数是否相等,相等返回 true。 | [ $a -eq $b ] 返回 false。 |
-ne | 检测两个数是否不相等,不相等返回 true。 | [ $a -ne $b ] 返回 true。 |
-gt | 检测左边的数是否大于右边的,如果是,则返回 true。 | [ $a -gt $b ] 返回 false。 |
-lt | 检测左边的数是否小于右边的,如果是,则返回 true。 | [ $a -lt $b ] 返回 true。 |
-ge | 检测左边的数是否大于等于右边的,如果是,则返回 true。 | [ $a -ge $b ] 返回 false。 |
-le | 检测左边的数是否小于等于右边的,如果是,则返回 true。 | [ $a -le $b ] 返回 true。 |
布尔运算符
运算符 | 说明 | 举例 |
---|---|---|
! | 非运算,表达式为 true 则返回 false,否则返回 true。 | [ ! false ] 返回 true。 |
-o | 或运算,有一个表达式为 true 则返回 true。 | [ $a -lt 20 -o $b -gt 100 ] 返回 true。 |
-a | 与运算,两个表达式都为 true 才返回 true。 | [ $a -lt 20 -a $b -gt 100 ] 返回 false。 |
逻辑运算符
运算符 | 说明 | 举例 |
---|---|---|
&& | 逻辑的 AND | [[ $a -lt 100 && $b -gt 100 ]] 返回 false |
|| | 逻辑的 OR | [[ $a -lt 100 || $b -gt 100 ]] 返回 true |
字符串运算符
运算符 | 说明 | 举例 |
---|---|---|
= | 检测两个字符串是否相等,相等返回 true。 | [ $a = $b ] 返回 false。 |
!= | 检测两个字符串是否相等,不相等返回 true。 | [ $a != $b ] 返回 true。 |
-z | 检测字符串长度是否为0,为0返回 true。 | [ -z $a ] 返回 false。 |
-n | 检测字符串长度是否不为 0,不为 0 返回 true。 | [ -n “$a” ] 返回 true。 |
$ | 检测字符串是否为空,不为空返回 true。 | [ $a ] a不为空则返回 true。 |
文件测试运算符
操作符 | 说明 | 举例 |
---|---|---|
-b file | 检测文件是否是块设备文件,如果是,则返回 true。 | [ -b $file ] 返回 false。 |
-c file | 检测文件是否是字符设备文件,如果是,则返回 true。 | [ -c $file ] 返回 false。 |
-d file | 检测文件是否是目录,如果是,则返回 true。 | [ -d $file ] 返回 false。 |
-f file | 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 | [ -f $file ] 返回 true。 |
-g file | 检测文件是否设置了 SGID 位,如果是,则返回 true。 | [ -g $file ] 返回 false。 |
-k file | 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 | [ -k $file ] 返回 false。 |
-p file | 检测文件是否是有名管道,如果是,则返回 true。 | [ -p $file ] 返回 false。 |
-u file | 检测文件是否设置了 SUID 位,如果是,则返回 true。 | [ -u $file ] 返回 false。 |
-r file | 检测文件是否可读,如果是,则返回 true。 | [ -r $file ] 返回 true。 |
-w file | 检测文件是否可写,如果是,则返回 true。 | [ -w $file ] 返回 true。 |
-x file | 检测文件是否可执行,如果是,则返回 true。 | [ -x $file ] 返回 true。 |
-s file | 检测文件是否为空(文件大小是否大于0),不为空返回 true。 | [ -s $file ] 返回 true。 |
-e file | 检测文件(包括目录)是否存在,如果是,则返回 true。 | [ -e $file ] 返回 true。 |
-S file | 判断某文件是否是socket,如果是,则返回 true。 | [ -S $file ] 返回 false。 |
-L file | 检测文件是否存在并且是一个符号链接,如果是,则返回 true。 | [ -L $file ] 返回 false。 |
八、Shell 流程控制
if else条件判断
if condition
then
command
...
fi
####################
if condition
then
command1
...
else
command2
...
fi
####################
if condition1
then
command1
...
elif condition2
then
command2
...
else
commandN
...
fi
if (($delta < 1024))
then
delta=$delta" B/S"
elif (( $delta >= 1024 && $delta < 1048576))
then
delta=`expr $delta / 1024`" KB/S"
else
delta=`expr $delta / 1048576`" MB/S"
fi
#下面三句话,作用相同
if (($delta < 1024));then delta1=$delta" B/S"; fi;
if [[ $delta -lt 1024 ]];then delta1=$delta" B/S"; fi;
if [ $delta -lt 1024 ];then delta1=$delta" B/S"; fi;
for循环
for var in item1 item2 ... itemN
do
command
...
done
#!/bin/bash
for((i=1;i<=5;i++));do
echo "这是第 $i 次调用";
done;
while循环
while condition
do
command
...
done
int=1 #此处=两边不能有空格
while [ $int -le 10 ] #while后面必须有空格
do
echo "OUTPUT: "$int
let "int++"
done
while true #无限循环
do
command
done
case分支选择
case 值 in
模式1)
command1
...
;;
模式2)
command2
...
;;
esac
site="baidu"
case "$site" in
"baidu") echo "baidu搜索"
;;
"google") echo "Google搜索"
;;
"taobao") echo "淘宝网"
;;
esac
continue 继续循环1
break 跳出循环2
九、Shell 函数
#!/bin/bash
demoFun()
{
echo "这是我的第一个 shell 函数!"
#返回值(0-255)可以显式得加:return返回。如果不加,将以最后一条命令运行结果,作为返回值。
}
echo "-----函数开始执行-----"
demoFun
echo "函数返回值为:"$?
echo "-----函数执行完毕-----"
函数返回值在调用该函数后通过 ? ∗ ∗ 来 获 得 。 ∗ ∗ ?** 来获得。** ?∗∗来获得。∗∗? 仅对其上一条指令负责。一旦函数返回后,其返回值没有立即保存入参数,那么其返回值将不再能通过 $? 获得。
注意:所有函数在使用前必须定义。调用函数仅使用其函数名即可。
十、Shell 输入/输出重定向
命令 | 说明 |
---|---|
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 之间的内容作为输入。 |
注意: 文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。
/dev/null 文件
/dev/null 是一个特殊的文件,如果希望执行某个命令,但又不希望在屏幕上显示输出结果,起到"禁止输出"的效果。那么可以将输出重定向到/dev/null:
command > /dev/null
如果希望屏蔽 stdout 和 stderr,可以这样写:
command > /dev/null 2>&1 #这里的 2 和 >之间不得有空格
十一、Shell 文件包含
和其他语言一样,Shell 也可以包含外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。
#!/bin/bash
#使用 . 号来引用test1.sh 文件
. ./test1.sh
# 或者使用以下包含test1.sh 文件
# source ./test1.sh
注:被包含的文件 test1.sh 不需要可执行权限。