shell编程入门
1. Shell是什么
Shell是用户与内核进行交互操作的一种接口,目前最流行的Shell成为bash Shell。Shell同时也是一门编程语言<解释型的编程语言>,即shell脚本。一个系统可以存在多个shell,可以通过cat /etc/shells命令查看系统中安装的shell,不同的shell可能支持的命令语法是不相同的。
1.1 第一个shell脚本
创建一个文件test.sh,扩展名为sh,即为一个shell脚本。shell脚本的第一行一般为:
#! /bin/bash echo "Hello World!"
解析:#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种Shell
echo 命令用于向窗口输出文本
1.2 运行Shell脚本的两种方式
① 首先赋予+x权限,然后输入脚本的绝对路径或相对路径
chmod +x ./test.sh #使脚本具有执行权限 ./test.sh #相对路径执行脚本 /root/test.sh #绝对路径执行脚本
② bash或sh + 脚本,不需要赋予x执行权限
bash /root/helloworld.sh sh helloworld.sh
2. Shell中的变量
2.1 Shell变量的类型
Linux Shell中的变量分为“系统变量”和“用户自定义变量”。系统变量一般包括$HOME,$PWD,$SHELL,$USER等等。通过set命令可以查看当前shell中所有变量,包括系统变量和用户自定义变量。
2.2 变量的定义与撤销
定义普通变量
语法:变量=值,如
STR="adb"
注意:定义变量时,变量名不加$符号。等号两侧不能有空格。双引号和单引号有区别,单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的,转义字符也无效,而双引号可以有变量和转义字符。
定义静态变量
readonly B=2
声明静态的变量B=2,不能使用unset撤销静态变量
撤销变量A
A=9 unset A
全局变量设置
export 变量名 可把变量提升为全局环境变量,可供其他shell程序使用
将命令的返回值赋给变量
A=`ls -la` A=$(ls -la)
A=`ls -la`反引号,运行里面的命令,并把结果返回给变量A。
A=$(ls -la)等价于反引号
2.3 Shell中的特殊变量
$? 表示上一个命令退出的状态
$$ 表示当前进程的编号
$0 表示当前脚本名称
$n 表示n位置的输入参数(n代表数字,n>=1)
$# 表示参数的个数,常用于循环
$*和$@ 都表示参数列表
注意:$*与$@区别
① $*和$@都表示传递给函数或脚本的所有参数,不被双引号""包含时,都以$1 $2 ... $n的形式输出所有参数
② 当它们被双引号""包含时,"$*"会将所有的参数作为一个整体,以"$1 $2 ... $n"的形式输出所有参数;"$@"会将各个参数分开,以"$1" "$2" ... "$n"的形式输出所有参数。
3. Shell运算符
Shell支持多种运算符,包括:
算数运算符、关系运算符、布尔运算符、逻辑运算符、字符串运算符、文件测试运算符
3.1 与数值有关的运算符:算数运算符和关系运算符
算数运算符
算数运算符有:
+ | - | * | / | % | = | == | != |
加 | 减 | 乘 | 除 | 取余 | 赋值 | 相等 | 不相等 |
(+ - * / %)使用格式:expr m + n 或 $((m+n))
注意:原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如awk和expr,expr最常用。expr是一款表达式计算工具,使用它能完成表达式的求值操作。expr运算符间要有空格。(== !=) 条件表达式要放在方括号之间,并且要有空格。
运算符实例:
#! /bin/bash val=`expr 2 + 2` echo "两数之和为:"$val val2=$((2+2)) echo "两数之和为:"$val2 expr `expr 2 + 3`\*4 echo `expr \`expr 2 + 3\`\*4` #或 echo $(((2+3)*4)) if [ 10 == 10 ] then echo "相等" fi
注意:乘号(*)、反引号(`)必须加反斜杠(\)实现转义
关系运算符
关系运算符有
-eq | -ne | -gt | -lt | -ge | -le |
相等判断 | 不相等判断 | 大于判断 | 小于判断 | 大于等于判断 | 小于等于判断 |
关系运算符使用格式: [ $a -eq $b ]
#!/bin/bash a=10 b=20 if [ $a -eq $b ] then echo "a等于b" elif [ $a -gt $b ] then echo "a大于b" else echo "a不大于b" fi
3.2 布尔运算符与逻辑运算符
布尔运算符
! | -o | -a |
非运算 | 或运算 | 与运算 |
实例:
#!/bin/bash a=10 b=20 if [ $a != &b ] then echo "a不等于b" fi if [ $a -lt 100 -a &b -gt 15 ] then echo "a小于100且b大于15" fi if [ $a -lt 100 -o &b -gt 15 ] then echo "a小于100或b大于15" fi
逻辑运算符
&& | || |
逻辑的AND | 逻辑的OR |
实例:
#!/bin/bash a=10 b=20 if [[ $a -lt 100 && $b -gt 100 ]] then echo "返回 true" fi if [[ $a -lt 100 || $b -gt 100 ]] then echo "返回 true" fi
注意:感觉布尔运算符与逻辑运算符除了字符表示不一样,意思是一样的
3.3 字符串运算符
= | != | -z | -n | str |
检测相等 | 检测不相等 | 检测字符串长度为0 | 检测字符串长度不为0 | 检测字符串为空 |
实例:
#!/bin/bash a="abc" b="efg" if [ $a = $b ] then echo "a等于b" fi if [ -z &a ] then echo "a长度为0" fi if [ &a ] then echo "字符串不为空"
3.4 文件测试运算符
-r file | -w file | -x file | -f file | -s file | -d file | -b file | -L file |
有读的权限 | 有写的权限 | 有执行的权限 | 文件存在并且是一个常规的文件 | 文件存在且不为空 | 文件存在并且是一个目录 | 文件存在并且是一个块设备 | 文件存在并且是一个链接 |
实例:
#!/bin/bash file="/var/test.sh" if [ -r $file ] then echo "文件可读" fi
4.Shell流程控制
4.1 if判断
if语句语法格式:
if condition
then
command1
[elif condition
then
command2... ]
[else
command3 ]
fi
示例:
#!/bin/bash read -p "please input your name:" NAME #printf '%s\n' $NAME if [ $NAME = root ] then echo "hello ${NAME}, welcome !" elif [ $NAME = itcast ] then echo "hello ${NAME}, welcome !" else echo "SB, get out here !" fi
condition判断语句
格式:[ condition ](注意condition前后要有空格)
#非空返回true,可使用$?验证(0为true, >1为false)如:
[ itcast ]
#空返回false
[ ]
4.2 for循环
第一种写法(常用)
for循环一般格式为:
for var in item1 item2 ... itemN
do
command1
done
写成一行:
for var in item1 item2 ... itemN; do command1; done;
示例:
#!/bin/bash for N in 1 2 3 do echo $N done #或写成一行 for N in 1 2 3; do echo $N; done #或 for N in {1..3}; do echo $N; done
第二种写法
实例:
#!/bin/bash for ((i = 0; i <= 5; i++)) do echo "welcome $i times" done #或写成一行 for ((i = 0; i <= 5; i++)); do echo "welcome $i times"; done
4.3 while循环
while使用格式:
while condition
do
command
done
示例:
#!/bin/sh int=1 while(( $int<=5 )) do echo $int let "int++" done
注意:Bash let命令,用于执行一个或多个表达式,变量计算中不需要加上$来表示变量。
4.4 case语句匹配
格式:
case 值 in
模式1)
commandN
;;
模式2)
commandN
;;
esac
case工作方式,取值后面必须为单词in,每一模式必须以右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至;;。示例:
echo '输入 1 到 4 之间的数字:' echo '你输入的数字为:' read aNum case $aNum in 1) echo '你选择了 1' ;; 2) echo '你选择了 2' ;; 3) echo '你选择了 3' ;; 4) echo '你选择了 4' ;; *) echo '你没有输入 1 到 4 之间的数字' ;; esac
注意:esac为作为case的结束标记。每个case分支用右圆括号,用两个分号(;;)表示break。跳出循环break命令和continue命令。break命令允许跳出所有循环(终止执行后面的所有循环)。continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。
5. Shell自定义函数
linux shell可以用户定义函数,然后在shell脚本中可以随便调用
shell中函数的定义格式如下:
[ function ] funname [()]
{
action;
[return int;]
}
说明:
- 1、可以带function fun()定义,也可以直接fun()定义,不带任何参数。
- 2、函数返回值,只能通过$?系统变量获得,可以显示加:return返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255)
- 3、必须在调用函数方法之前,先声明函数,shell脚本是逐行运行,不像其它语言一样先预编译
示例:
#! /bin/bash function fSum() { echo $1,$2; return $(($1+$2)); } fSum 2 3; total=$? echo "total=\$? 第一次调用\$?后的返回结果: "$total fSum 5 7 total=$? echo "total=\$?,\$? 两次调用后的返回结果,\$total=$total \$?=$?"; echo "-------------------------------------------" funWithReturn(){ echo "这个函数会对输入的两个数字进行相加运算..." echo "输入第一个数字: " read aNum echo "输入第二个数字: " read anotherNum echo "两个数字分别为 $aNum 和 $anotherNum !" return $(($aNum+$anotherNum)) } funWithReturn echo "输入的两个数字之和为 $? !"
6. 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)。
输出重定向
重定向一般通过在命令间插入特定的符合来实现。可以选择覆盖或者追加的模式添加内容
command1 > file1 或 command1 >> file1
示例:
$ who > users echo "hello world" > users echo "hello shell" >> users
输入重定向
输入重定向可以从文件获取输入,语法为:
command1 < file1
示例,接着以上示例,统计users文件的行数,如:
wc -l < users
输入与输出重定向结合
command1 < infile > outfile
说明:同时替换输入和输出,执行command1,从文件infile读取内容,然后将输出写入到outfile中。
其他重定向
$ command > file 2>&1 #或者 $ command >> file 2>&1
说明:
1、文件描述符0通常是标准输入(STDIN),1是标准输出(STDOUT),2是标准错误输出(STDERR)
2、将 stdout 和 stderr 合并后重定向到 file
Here Document
Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。
它的基本的形式如下:
command << delimiter document delimiter
它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。
注意:
结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。
开始的delimiter前后的空格会被忽略掉。
示例,在命令行中通过 wc -l 命令计算 Here Document 的行数:
$ wc -l << EOF 欢迎来到 菜鸟教程 www.runoob.com EOF 3 # 输出结果为 3 行 $
7.设置后台进程
& 放在启动参数后面表示设置此进程为后台进程。默认情况下,进程是前台进程,这时就把Shell给占据了,我们无法进行其他操作,对于那些没有交互的进程,很多时候,我们系统将其在后台启动,可以在启动参数的时候加一个‘&’实现这个目的。
8. 脚本调试
两种方式:
① 输入命令:sh -vx helloworld.sh
② 或者在脚本中增加set -x