Linux——Shell脚本使用

概述

这里只是对shell脚本使用的一个简单介绍,实际上Shell所涉及的东西远远不止如此,但是这些内容能对Shell有一个基础的理解。

脚本解析器

shell常用的解析器主要是bash和sh,可以通过下面命令查看

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash

可以通过下面的命令查看默认的解释器

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# echo $SHELL
/bin/bash

创建并执行脚本

shell脚本是以sh为后缀的文件。文件内容就是需要具体执行的脚本命令。

创建脚本

在root目录创建一个名字为hello.sh的脚本

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# touch hello.sh
[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# vi hello.sh

## 文件内部添加内容,无需其他内容,执行脚本的时候会直接执行文件内部的语句
echo "helloworld"

启动脚本

  1. 使用bash启动

使用bash启动脚本需要在命令前添加bash语句

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# bash /root/hello.sh 
helloworld

  1. 直接输入脚本绝对路径执行脚本

这种方式不需要添加sh或者bash命令。直接执行脚本

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# ./hello.sh
helloworld

++需要注意的++

直接只用./进行访问可能会遇见权限问题

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# ./hello.sh
-bash: ./hello.sh: Permission denied

此时需要添加权限

chmod 777 variable.sh 

变量

自定义变量

我们可以直接通过key=value在linux中设置自己的变量。

设置变量的时候需要注意下面的问题:

  1. 变量名称可以由字母、数字和下划线组成,但是不能以数字开头
  2. 变量设置对等号附近的空格敏感,所以在设置参数的时候等号两侧不能有空格
  3. 变量默认的为字符类型,不能进行运算
  4. 如果变量值中有空格,需要使用单引号或者双引号包裹
  5. 如果变量值中存在其他变量需要使用双引号。

声明一个变量

这种方式可以声明一个name的变量

echo "赋值新变量:设置变量name为dai"
name=dai
echo $name

脚本输出

赋值新变量:设置变量name为dai
dai

修改一个变量

下面语句尝试修改name变量

echo "重新赋值:修改变量name为dai2"
name=dai2
echo $name

脚本输出

重新赋值:修改变量name为dai2
dai2

删除一个变量

将name变量进行删除

echo "撤销变量:name"
unset name
echo $name

脚本输出

撤销变量:name

声明一个只读的变量

此时尝试删除此变量后此变量依旧可以正常输出

echo "声明只读的变量:name_read"
readonly name_read="readonly"
echo $name_read
unset name_read
echo $name_read

脚本输出

声明只读的变量:name_read
readonly
readonly

输出一个带变量的运算结果

尝试输出一个变量的运算结果,此时使用双引号可以正常输出,而单引号会将变量作为字符串输出

echo "双引号中识别变量"
echo "hello $name_read"
echo "单引号中识别变量"
echo 'hello $name_read'

脚本输出

双引号中识别变量
hello readonly
单引号中识别变量
hello $name_read

将命令结果赋值给变量

此方法可以将linux中命令的结果赋值给变量,下面使用命令或者$(命令)都是可以的

echo "将一个命令结果给其他变量方法1"
name1=`date`
echo $name1
echo "将一个命令结果给其他变量方法2"
name2=$(date)
echo $name2

脚本输出

将一个命令结果给其他变量方法1
Wed Oct 7 13:33:16 CST 2020
将一个命令结果给其他变量方法2
Wed Oct 7 13:33:16 CST 2020

脚本中变量的范围

脚本中声明变量在控制台中尝试获取

现在最开始的hello.sh修改成下面样子,对一个this_date变量进行赋值。

echo "输出this_date"
echo $this_date
this_date=`date`
echo "设置完后输出this_date"
echo $this_date

此时执行后可以看到结果已经声明的变量内容。但是后续尝试在控制台中获取此变量却没有获取到结果,可以发现脚本中声明的变量并没有传递到控制台中

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# ./hello.sh 
输出this_date

设置完后输出this_date
Wed Oct 7 13:48:39 CST 2020

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# echo $this_date

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]#

在控制台中声明变量,脚本中尝试获取

此时可以发现在外部声明的变量在脚本中同样无法获取。

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# this_date=`date`
[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# echo $this_date
Wed Oct 7 13:53:06 CST 2020
[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# ./hello.sh 
输出this_date

设置完后输出this_date
Wed Oct 7 13:53:23 CST 2020
[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# 

这是因为上面脚本执行是当前shell中打开一个子shell来执行脚本内容,当脚本内容结束,则子shell关闭,回到父shell中。如在子shell中设置的当前变量,不做特殊通道处理的话,父shell是不可见的。

将自定义变量设置为全局变量

我们可以将自定义变量设置为全局变量,这边其他的shell脚本也可以使用。

这样操作需要将之前的脚本最后添加下面内容:

export this_date

此时再进行操作就可以获得结果

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# ./hello.sh 
输出this_date

设置完后输出this_date
Wed Oct 7 13:58:17 CST 2020
[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# echo $this_date
Wed Oct 7 13:53:06 CST 2020

当然也可以尝试修改/etc/profile文件通过添加export key=value来设置变量为系统变量。不过不要忘了最后执行source /etc/profile命令

脚本参数变量

当脚本存在输入参数的时候,可以使用n 、 n、n#、∗ 、 *、@来获取参数的内容

$n

可以用$n来表示哪个参数。0 : 为 脚 本 名 称 ; 1 − n 表 示 第 几 个 参 数 , 其 中 1 − 9 表 示 为 0:为脚本名称;1-n表示第几个参数,其中1-9表示为01n19n,10以上需要包裹大括号${n}

$#

用来获取参数个数

$*

命令行中所有的参数,$*把所有的参数看成一个整体

$@

代表命令行中所有的参数,$@把每个参数区分对待

实例

现在创建一个param.sh的脚本内容如下

echo "$0 $1 $2"
echo $#
echo $*
echo $@

其输出内容

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# ./param.sh param1 param2
./param.sh param1 param2
2
param1 param2
param1 param2

命令执行结果变量

$?变量可以证明上一个命令是否正确执行。如果为0在证明执行正确,否则则证明执行出现了问题

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# ./param.sh param1 param2
./param.sh param1 param2
2
param1 param2
param1 param2
[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# echo $?
0
[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# asdad
-bash: asdad: command not found
[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# echo $?
127

计算

计算的语法

  1. *号需要转义为*
  2. 运算指的都是整数的运算
  3. 运算以expr开始,符号间需要空格

运算符号

符号作用
+
-
*
/
%取余

嵌套运算

当存在(a + b) * C这种多个运算嵌套的时候下面两种方式都能实现结果

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# expr `expr 1 + 2` \* 3
9
[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# rest=$[(1+2)*3]
[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# echo $rest
9

判断

判断语句的语法

## 注意前后要有空格
[ 判断语句 ]

判断条件

符号作用
=字符串比较
-lt小于
-le小于等于
-eq等于
-gt大于
-ge大于等于
-ne不等于
-r有读的权限
-w有写的权限
-x有执行的权限
-f文件存在并且是一个常规的文件
-e文件存在
-d文件存在并是一个目录
-s文件存在且不为空
-L文件存在且是一个链接

使用示例

使用下面方式可以实现结果的输出

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# [ 23 -ge 26 ] && echo ture || echo false
false
[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# [ -w hello.sh ] && echo ture || echo false
ture
[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# [ -d hello.sh ] && echo ture || echo false
false

流程控制

if

shell 中的if流程格式为下面格式,最后以fi结束。课条件判断一样[]和条件公式需要空格分隔,而if后面也需要空格分隔

if [ 条件判断式 ] 
    then 
        逻辑1 
elif 条件判断式
    then 
	    逻辑2
else 
        逻辑3
fi 

示例

创建下面的一个脚本用来表示if的使用方式

if [ $1 -eq 1 ] ;
then 
echo "输入逻辑1"
elif [ $1 -eq 2 ] ;
then 
echo "输入逻辑2"
elif [ $1 -eq 3 ] ;
then 
echo "输入逻辑3"
else echo "未知逻辑"
fi 

返回内容

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# ./test.sh 1
输入逻辑1
[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# ./test.sh 2
输入逻辑2
[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# ./test.sh 3
输入逻辑3
[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# ./test.sh 7
未知逻辑

++需要注意++

和上面使用简单逻辑的示例不同,这里涉及多行判断,此时可能会遇见换行符的问题,

通过vim编辑脚本,在命令行模式下输入:set ff如果结果为fileformat=dos则需要手动输入置:set ff=unix来设置文件对应系统

case

基本语法

case逻辑以case开始以esac结束

case $变量 in 
  值1)
    程序1 ;;
  值2)
    程序2 ;;
  值3)
    程序3 ;;
  *)
    其他 ;; 
esac

示例

将上面if的逻辑改为case后脚本内容如下

case $1 in 
  1)
    echo "case输入逻辑1" ;;
  2)
    echo "case输入逻辑2" ;;
  3)
    echo "case输入逻辑3" ;;
  *)
    echo "case未知逻辑" ;; 
esac 

输出内容如下

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# ./test.sh 8
case未知逻辑
[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# ./test.sh 1
case输入逻辑1

for

基本语法

for (( 初始值;循环控制条件;变量变化 )) 
  do 
    程序 
  done

示例

上面内容可以使用一个简单的i循环来实现其效果

for((i=0;i<=10;i++))
do
        echo $i
done

最终输出内容

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# ./test.sh
0
1
2
3
4
5
6
7
8
9
10

for 还能实现一种类似foreach的语法

for (变量 in 值1 值2 值3)do 程序;
 done

示例

将上面语法改造下,用来循环输入参数

for i in $*
do
        echo $i
done

++注意++

使用 for i in "$*"的时候整个参数会被看成一个整体,而只循环1次

执行后结果

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# ./test.sh 1 3 5 6
1
3
5
6

while

基础语法

# 第一种
while [ 条件判断式 ] 
  do 
    程序
  done

# 第二种
while((表达式))
do
	程序
done

示例

将上面的i循环改造为while格式

i=0
while [ $i -le 10 ]
do
	echo $i
	i=$[$i+1]
done

最终输出的内容和使用i循环是一致的

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# ./test.sh 
0
1
2
3
4
5
6
7
8
9
10

函数

自定义函数

shell中我们可以使用函数来实现一些复杂的逻辑,这里只介绍自定义函数的内容

++注意内容++

  1. 函数需要提前声明,shell脚本是逐行运行。不会像其它语言一样先编译。
  2. 函数返回值,只能通过$?系统变量获得

函数声明的格式

function  funname()
{
	Action;
	[return int;]
}

示例

创建一个汇总输入参数和的函数

sum_param=0
function  rest() {
for i in $*
do
     echo $i
     sum_param=$[$sum_param + $i]	
done
}
rest $*
echo "输入参数和为:$sum_param"

最终返回结果

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# ./test.sh 2 4 5
2
4
5
11

在脚本中提供用户输入

shell提供的输入语法

read -t 等待时间 -p "提示语句"  变量名称

示例

read -t 5 -p "请在5秒钟内输入一个数字" NUM
echo "输入的数字为:$NUM"

脚本执行的结果

[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# ./test.sh 
请在5秒钟内输入一个数字8
输入的数字为:8
[root@iZbp1buyhgwtrw6hrp2ugjZ ~]# 


个人水平有限,上面的内容可能存在没有描述清楚或者错误的地方,假如开发同学发现了,请及时告知,我会第一时间修改相关内容。假如我的这篇内容对你有任何帮助的话,麻烦给我点一个赞。你的点赞就是我前进的动力


版权声明:本文为qq330983778原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。