shell脚本----shell基本语法及实现一个简单的进度条

shell脚本编写进度条

shell脚本及执行方式

Shell脚本,是一种为shell编写的脚本程序。shell编程和Java,Python和PHP编程类似,只要有一个可以编写代码的文本编辑器和一个可以解释并执行代码的解释器就可以了。
来看个简单的shell脚本:
touch一个myshell.sh,其中.sh是shell脚本的后缀

#!/bin/bash

echo "hello shell!"

在这里解释一下第一行,#! 是一个约定的标记,它告诉系统应该用什么解释器来执行这个脚本。后面的/bin/bash就是解释器了。
要执行这个shell脚本有两种方式:

  1. 作为可执行程序
    我们创建的文件默认是没有可执行权限的,利用chmod加上权限就可以执行了
    这里写图片描述

  2. 作为解释器参数
    直接运行解释器,其参数就是 shell 脚本的文件名,以这种方式运行的脚本就不需要在第一行指定解释器信息,写了也没用
    这里写图片描述

来谈谈这两种方式的本质

第一种方式: shell会fork创建一个子进程并调用exec来执行这个脚本程序,而且exec有一种机制,如果要执行的是一个文本文件而且第一行给出了解释器,那么就直接用解释器程序的代码段直接替换当前进程然后开始执行,而这个文本文件被当做命令行参数传给解释器。
第二种方式: 第二种方式也就是将文本文件传给解释器做命令行参数来执行。

需要注意的是:执行某些命令,不一定要创建子进程!这些不需要创建子进程的命令,叫做shell的内置命令,由父bash亲自执行。例如:cd命令就是一个内置命令。

shell变量

shell是弱类型语言,看看下面的例子:

#!/bin/bash

a=1
b=3.14
c="hello"
d='m'

echo $a
echo $b
echo $c
echo $d

来看看运行结果:
这里写图片描述
可以看到shell变量中可以放整型、浮点型、字符型、字符串等等很多东西,在这里需要强调的一点是:变量名和等号直接不能有空格,如果带了空格会被shell解释为命令和命令行参数。下面是shell变量的命名规则:

  • 首个字符必须为字母(a-z,A-Z)
  • 中间不能有空格,可以使用下划线(_)
  • 不能使用标点符号
  • 不能使用bash里的关键字(可用help命令查看保留关键字)。
shell变量的使用及删除

当使用一个变量或输出的时候需要在变量名前加 $ 符号,但一般变量赋值的时候不需要使用,也可以给变量名加上花括号{ },这样是为了方便解释器识别边界。
如果我们要对变量进行计算时,就需要用双圆括号(( )),双圆括号中的内容是类C的,如下:

#!/bin/bash

a=1
b=2

c=$((a+b))

echo ${a}
echo ${b}
echo ${c}

这里写图片描述

如果我们需要删除一个变量就需要用到unset命令:

#!/bin/bash

mystr="hello word"

echo $mystr
unset mystr
echo $mystr

这里写图片描述
被删除的变量内容会被清空,可以看到第二个echo语句输出了一个空串

只读变量

被readonly修饰的变量时只读变量,不可以修改它的值,同样也不能被删除

#!/bin/bash

readonly mystr="hello word"
echo ${mystr}

mystr="this is string"
echo $mystr

unset mystr
echo $mystr

这里写图片描述

变量分类
  1. 本地变量:局部变量在脚本或命令中定义,只存在于当前shell中,其他shell启动的程序不能访问

  2. 环境变量:所有的程序,包括shell启动的程序,都能访问环境变量,可以从父进程传给子进程,利用printenv命令可以查看当前shell的环境变量,如果利用export可以将本地变量导出为环境变量

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

shell条件测试

测试命令test和 [

直接上例子:

#!/bin/bash

read a #从标准输入读入

test $a -eq 100 

echo $?

看最后一条语句,echo $? 是查看上面最近一个程序的退出码,在shell脚本中,测试条件成立退出码为0,不成立为非0
这里写图片描述
除了上面的test还可以利用 [ ] 来进行测试:
注意:在使用 [ ] 的时候每个变量之间要有空格,变量和左右方括号之间也需要有空格,不然就会报错

#!/bin/bash

read a

[ $a -eq 100 ] 

echo $?

这里写图片描述
从上面的例子可以注意到,我们是利用 -eq 来进行比较的,对于不同的类型,测试选项也不同

  • 整数:-eq 等于、-ne 不等于、-le 小于等于、-ge 大于等于、-lt 小于、-gt 大于
  • 字符串:==/=!=-z-n
  • 文件:-d-f-b-c

比较字符串的时候==和=都可以用来判断是不是相等,-z是用来判断一个字符串是否为空串,-n是判断一个字符串是否为非空串。
-d 判断是否为目录;-f 判断是否为普通文件;-b 是否为块设备;-c 是否为字符设备,来看例子:

#!/bin/bash

[ -d / ]            #是否为目录
echo $?

[ -c /dev/tty ]     #是否为块设备
echo $?

[ -b /dev/sda ]     #是否为字符设备
echo $?

[ -f ./myshell.sh ] #是否为普通设备
echo $?

这里写图片描述

多条件测试
  • -a:逻辑与
  • -o:逻辑或
  • ! :逻辑非

例子:

#!/bin/bash

myint=100

#判断myshell.sh是不是普通文件而且myint是否等于200
[ -f ./myshell.sh -a $myint -eq 200 ]
echo $?

#判断myint是否不等于200并取反
[ ! $myint -ne 200 ]
echo $?

#判断myint是否等于100或者myshell.sh是否是普通文件
[ $myint -eq 100 -o -f ./myshell.sh ]
echo $?

这里写图片描述

条件分支结构语句

if/then/elif/fi

shell脚本的条件语句格式如下:

1.单分支判断语句

if 条件
then 
    条件成立执行的语句
fi

2.双分支判断语句

if 条件
then 
    条件成立执行的语句
else
    条件不成立执行的语句
fi

3.多分支判断语句

if 条件1;then 
    条件1成立执行的语句
elif 条件2;then
    条件2成立执行的语句
else
    条件都不成功执行的语句 
fi

来总结一下,shell脚本的条件判断语句是用 if、then、elif、else、fi 这几条命令来实现的,和C语言很类似,但要注意的是后面一定要有fi,shell脚本中控制分支结构结束都要和开头的单词相反,例如,if <–> fi,case <–> esac
还有一点就是如果两条命令写在同一行则需要用 ; 号隔开,一行只写一条命令就不需要写分号了。另外,then后面有换行,但这条命令没写完Shell会自动续行,把下一行接在then后面当作一条命令处理。和 [ 命令一样要注意命令和各参数之间必须用空格隔开
在这里直接上一个多分支的例子:

#!/bin/bash

read data

if [ $data -eq 100 ];then
    echo "this is 100"
elif [ $data -eq 200 ]
then
    echo "this is 200"
else
    echo "hello word"
fi

这里写图片描述

在C语言中如果我们在if中什么都不做就可以写一条空语句 ; 或者什么都不写,但在shell脚本中如果出现空语句就会报错,所以在shell脚本中用 这个空命令,这个命令什么事都不做,但它的退出码总是为真,在这里就不举例子了。

再补充一条:if命令的参数组成了一条子命令,如果该子命令的Exit Status为0(表示真),则执行then后面的子命令。如果Exit Status非 0(表示假),则执行elif、else或者fi后面的子命令。if后面的子命令通常是测试命令,除了 [ 和 test 命令,还可以放其他命令,只要该命令退出码为0,1来表明执行就可以

case/esac

在C语言中有switch/case语句,在shell脚本中有case命令和它的功能是类似的,直接看个例子吧:

#!/bin/bash

read data

case $data in
    "100" )
        echo "this is 100"
    ;;              
    "200" )
        echo "this is 200"
    ;;
    "300" )
        echo "this is 300"
    ;;
    * )                  
        echo "default"
    ;;
esac

C语言的case只能匹配整型或字符型常量表达式,而Shell脚本的case可以匹配字符串和通配符,在匹配完成要在后面加一个 ) ,每个匹配分支可以有若干条命令,最后必须以;;结束,就类似与C语言中的break。而代码中最后一行的 * 就相当于C语言中的default一样。
这里写图片描述

循环语句

1.while循环

while循环只要while语句为真就执行

while 条件 
do 
    语句 
done

上例子:

#!/bin/bash

i=$1

while [ $i -lt 5 ]
do
    echo "this is $i"
  # ((i++))
    let i++
done

看程序中,我们对循环变量做改变的时候,用了两种方式,其中一种是最开始说的双圆括号,还有一种是可以利用 let 命令

这里写图片描述

2.for循环

shell脚本对for循环有两种:

(1) 类C的写法
同样是利用我们上面的双圆括号,不多做解释了

#!/bin/bash

i=0

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

这里写图片描述
(2) for in 循环
直接上两个特色的例子:

#!/bin/bash

for i in {a..c}{1..3}
do
    echo "hello $i"
done

这里写图片描述

#!/bin/bash

for i in {a,b,c} {1,2,3}
do
    echo "hello $i"
done

这里写图片描述

可以看到这两段代码的区别就是,第二段代码的两个花括号之间有一个空格,第一个不带空格的是将两个花括号中的内容进行排列组合,而不带空格的话是分别遍历两个花括号中的内容。当然也可以只有一个花括号,花括号中的内容可以像第二个一样枚举出来,也可以类似第一个直接利用 . .

3. until循环

shell还有一种自己特有的循环是until循环
until循环和while循环的写法很像,但是until循环是当条件为假就执行循环体

#!/bin/bash

i=0
until [ $i -ge 10 ]
do
    echo "hello $i"
    let i++
done

这里写图片描述

shell函数

看看shell函数的格式:

[function] funcName() 
{ 
    语句 
    [return 返回值] 
} 

shell的函数没有参数列表,[ ]中的内容是可选的,function标识这是一个函数,后面跟函数名。也可以不加function直接写出函数名。shell函数的返回值也是可选的,只能返回整数,如果没有给出return,则默认返回最后一条语句的执行结果

#!/bin/bash

function myfun()
{
    echo "this is a function!"
    return 1
}
myfun

shell在定义函数时并不执行函数体中的命令,就像定义变量一样,只是给myfun这个名字一个定义, 到后面调用 myfun函数的时候才执行函数体中的命令。shell脚本中调用函数不用带括号,而且shell函数必须先定义再调用
这里写图片描述

函数传参

shell函数虽然没有参数列表,但是依然可以给它传参。来看看下面的例子:

#!/bin/bash

function myfun()
{
    echo "this is function"
    echo $0
    echo $1
    echo $2
    echo $#
    echo $@
    echo "this is function!"
}
myfun str1 str2

shell在调用函数的时候可以在函数后面跟上参数,在函数体内部就可以利用之前说过的获取命令行参数的方法来拿到函数参数
这里写图片描述
解释一下这些变量:

  • $0:文件名,相当于C语言main函数的argv[0]
  • $1:第一个参数,相当于argv[1]
  • $#:参数个数
  • $@:参数列表

猜你喜欢

转载自blog.csdn.net/qq_34021920/article/details/80929358