Shell编程
前言语
Linux修仙之路初级篇到这里就快要接近尾声了,一些常用的干货,基础的运用都给大家一一列举了,小编也是自学走过来的,很多时候明白大家一下子不能理解的心情,所以大家可以私信留言我,一起探讨交流,废话不多说,干货走着!
Shell简介
- Shell 是一个用 C 语言编写的程序
- 是用户使用 Linux 的桥梁
- Shell 既是一种命令语言,又是一种程序设计语言
- 用户通过Shell 这个界面访问操作系统内核的服务
- Ken Thompson 的 sh 是第一种 Unix Shell
- Windows Explorer 是一个典型的图形界面 Shell
- Shell 是一个命令解释权
- 用户可以用 Shell 来启动、挂起、停止甚至是编写一些程序
第一个Shell脚本
老生常谈的HelloWorld
#!/bin/bash
echo "Hello World !"
#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell。
Ps:echo 命令用于向窗口输出文本。
运行 Shell 脚本两种方法
1、作为可执行程序
- 将上面的代码保存为 test.sh
- cd 到相应目录
chmod +x ./test.sh
#使脚本具有执行权限
./test.sh
#执行脚本
注意,一定要写成 ./test.sh,而不是 test.sh
Ps:运行二进制的程序若直接写 test.sh,linux 系统会去 PATH 里寻找有没有叫 test.sh 的,而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 里,你的当前目录通常不在 PATH 里,所以写成 test.sh 是会找不到命令的,要用 ./test.sh是 告知系统在当前目录找。
2、作为解释器参数
直接运行解释器,参数为 shell 脚本的文件名
如: /bin/sh test.sh/bin/php test.php
这种方式运行的脚本,不需要在第一行指定解释器信息。
Shell变量
命名规则
- 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头
- 中间不能有空格,可以使用下划线(_)
- 不能使用标点符号
- 不能使用bash里的关键字(可用help命令查看保留关键字)
变量赋值
示例:
your_name="handsomeboy"
Ps:变量名和等号之间不能有空格。
for file in 'ls /etc'
或
for file in $(ls /etc)
Ps:将 /etc 下目录的文件名循环出来
调用变量
示例:
your_name="beautifulgirl"
echo $your_name
echo ${your_name}
Ps:变量名外面的花括号是可选的,加不加都行。
加花括号是为了帮助解释器识别变量的边界。
使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。
删除变量
示例:
unset variable_name
Ps:变量被删除后不能再次使用。
unset 命令不能删除只读变量
#!/bin/sh
myUrl="https://https://blog.csdn.net"
unset myUrl
echo $myUrl
变量类型
- 局部变量
局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。 - 环境变量
所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。 - shell变量
shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行
Shell字符串
单引号
str='this is a string'
单引号字符串的限制
- 单引号里的任何字符都会原样输出,单引号字符串中的变量无效;
- 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。
双引号
示例:
your_name='handsomeboy'
str="Hello, I know you are a \"$your_name\"! \n"
echo -e $str
结果:
Hello, I know you are a "handsomeboy"!
双引号的优点
- 双引号里可以有变量
- 双引号里可以出现转义字符
拼接字符串
your_name="handsomeboy"
# 使用双引号拼接
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1
# 使用单引号拼接
greeting_2='hello, '$your_name' !'
greeting_3='hello, ${your_name} !'
echo $greeting_2 $greeting_3
结果
# 使用双引号拼接
hello, runoob ! hello, handsomeboy!
# 使用单引号拼接
hello, runoob ! hello, ${your_name} !
获取字符串长度
示例:
#从字符串第 2 个字符开始截取 4 个字符
string="runoob is a great site"
echo ${string:1:4}
结果:
unoo
Ps:第一个字符的索引值为 0。
查找子字符串
示例:
#查找字符 i 或 o 的位置(哪个字母先出现就计算哪个)
string="runoob is a great site"
echo `expr index "$string" io`
结果:
4
Ps:以上脚本中 ` 是反引号,而不是单引号 '
Shell数组
数组概论
- bash支持一维数组(不支持多维数组)
- 数组的大小没有限定
- 数组元素的下标由 0 开始编号
- 利用下标获取元素,下标可以是整数或算术表达式,其值应大于或等于 0
定义数组
在 Shell 中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为:
数组名=(值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
Ps:可以不使用连续的下标,而且下标的范围没有限制。
读取数组
读取数组元素值的一般格式是:
${数组名[下标]}
示例:
valuen=${array_name[n]}
# 使用 @ 符号可以获取数组中的所有元素,例如:
echo ${array_name[@]}
获取数组长度
示例:
# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
lengthn=${#array_name[n]}
Shell注释
以 # 开头的行就是注释
通过每一行加一个 # 号设置注释
多行注释
:<<EOF
注释内容...
注释内容...
EOF
:<<'
注释内容...
注释内容...
'
:<<!
注释内容...
注释内容...
!
Shell 传递参数
我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n。n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……
其他常用
选项 | 意义 |
---|---|
$# | 传递到脚本的参数个数 |
$* | 以一个单字符串显示所有向脚本传递的参数。 |
如"$*“用「”」括起来的情况 | 以"$1 $2 … $n"的形式输出所有参数。 |
$$ | 脚本运行的当前进程ID号 |
$! | 后台运行的最后一个进程的ID号 |
$@ | 与$*相同,但是使用时加引号,并在引号中返回每个参数。 |
如"$@“用「”」括起来的情况 | 、以"$1" “ 2 " … " 2" … " 2"…"n” 的形式输出所有参数。 |
$- | 显示Shell使用的当前选项,与set命令功能相同。 |
$? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。 |
Shell 基本运算符
Shell 和其他编程语言一样,支持多种运算符,包括:
- 算数运算符
- 关系运算符
- 布尔运算符
- 字符串运算符
- 文件测试运算符
Ps:原生bash不支持简单的数学运算,但是可以通过其他命令来实现
例如 awk 和 expr,expr 最常用。
示例
#!/bin/bash
val=`expr 2 + 2`
echo "两数之和为 : $val"
结果
4
运算符 | 说明 | 举例 |
---|---|---|
+ | 加法 | 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 为 10,变量 b 为 20:
运算符 | 说明 | 举例 |
---|---|---|
-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。 |
布尔运算符
下表列出了常用的布尔运算符,假定变量 a 为 10,变量 b 为 20:
运算符 | 运算 | 说明 | 举例 |
---|---|---|---|
! | 非运算 | 表达式为 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。 |
逻辑运算符
以下介绍 Shell 的逻辑运算符,假定变量 a 为 10,变量 b 为 20:
运算符 | 说明 | 举例 |
---|---|---|
&& | 逻辑的 AND | [[ $a -lt 100 && $b -gt 100 ]] 返回 false |
ll | 逻辑的 OR | [[ $a -lt 100 或 $b -gt 100 ]] 返回 true |
字符串运算符
下表列出了常用的字符串运算符,假定变量 a 为 “abc”,变量 b 为 “efg”:
运算符 | 说明 | 举例 |
---|---|---|
= | 检测两个字符串是否相等,相等返回 true。 | [ $a = $b ] 返回 false。 |
!= | 检测两个字符串是否不相等,不相等返回 true。 | [ $a != $b ] 返回 true。 |
-z | 检测字符串长度是否为0,为0返回 true。 | [ -z $a ] 返回 false。 |
-n | 检测字符串长度是否不为 0,不为 0 返回 true。 | [ -n “$a” ] 返回 true。 |
$ | 检测字符串是否为空,不为空返回 true。 | [ $a ] 返回 true。 |
echo和printf命令
$ echo "Hello, Shell"
结果:Hello, Shell
$ printf "Hello, Shell\n"
结果:Hello, Shell
Shell test 命令
数值测试
示例:
num1=100
num2=100
if test $[num1] -eq $[num2]
then
echo '两个数相等!'
else
echo '两个数不相等!'
fi
结果:
两个数相等!
字符串测试
示例:
num1="ru1noob"
num2="runoob"
if test $num1 = $num2
then
echo '两个字符串相等!'
else
echo '两个字符串不相等!'
fi
结果
两个字符串不相等!
文件测试
参数 | 说明 |
---|---|
-e 文件名 | 如果文件存在则为真 |
-r 文件名 | 如果文件存在且可读则为真 |
-w 文件名 | 如果文件存在且可写则为真 |
-x 文件名 | 如果文件存在且可执行则为真 |
-s 文件名 | 如果文件存在且至少有一个字符则为真 |
-d 文件名 | 如果文件存在且为目录则为真 |
-f 文件名 | 如果文件存在且为普通文件则为真 |
-c 文件名 | 如果文件存在且为字符型特殊文件则为真 |
-b 文件名 | 如果文件存在且为块特殊文件则为真# Shell流程控制 |
示例
cd /bin
if test -e ./bash
then
echo '文件已存在!'
else
echo '文件不存在!'
fi
结果
文件已存在!
Shell流程控制
if
if condition
then
command1
command2
...
commandN
fi
while
while condition
do
command
done
for
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
Until
until condition
do
command
done
case…esac
case 值 in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac
break
跳出当前循环
Shell 函数
linux shell 可以用户定义函数,然后在shell脚本中可以随便调用。
[ function ] funname [()]
{
action;
[return int;]
}
Ps:
1、可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
2、参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255)
示例
#!/bin/bash
demoFun(){
echo "这是我的第一个 shell 函数!"
}
echo "-----函数开始执行-----"
demoFun
echo "-----函数执行完毕-----"
结果
-----函数开始执行-----
这是我的第一个 shell 函数!
-----函数执行完毕-----
示例
#!/bin/bash
funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum 和 $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"
结果
这个函数会对输入的两个数字进行相加运算...
输入第一个数字:
1
输入第二个数字:
2
两个数字分别为 1 和 2 !
输入的两个数字之和为 3 !
Ps:函数返回值在调用该函数后通过 $? 来获得。
所有函数在使用前必须定义。
必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用。
调用函数仅使用其函数名即可。
Shell 输入/输出重定向
大多数 UNIX 系统命令从你的终端接受输入并将所产生的输出发送回到您的终端。一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端。同样,一个命令通常将其输出写入到标准输出,默认情况下,这也是你的终端。
重定向命令列表如下:
命令 | 说明 |
---|---|
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 之间的内容作为输入。 |
Ps:
文件描述符
0 通常是标准输入(STDIN)
1 是标准输出(STDOUT)
2 是标准错误输出(STDERR)。
文件调用
示例
. filename
# 注意点号(.)和文件名中间有一空格
source filename
小编只是简单汇总了Shell编程的基础部分,适合于小白同学们探讨学习,希望对大家有帮助的可以一键三连呀!