shell编程入门(bash)

一、背景知识

(1)什么是shell?

高大上的解释,往往让人摸不住头脑。一句话概括就是:shell编程就是对一堆Linux命令的逻辑化处理。

(2)为什么需要shell?

譬如我们要在linux下创建一个文件a.c,可以touch a.c 但是如果我现在是用在linux下创建100个文件,分别为a1.c  a2.c.....a100.c 如果这时候还是手工去命令行下执行命令创建也可以,但是很累。最好的做法就是把创建过程写成一个shell脚本程序(for循环),然后去执行这个shell脚本程序,执行这个程序的效果和手工在命令行输入那些命令效果一样的。

(3)如何运行shell(.sh)程序?

第一种:./xx.sh,和运行二进制可执行程序方法一样。这样运行shell要求shell程序必须具有可执行权限。chmod a+x xx.sh来添加可执行权限。

第二种:source xx.sh,source是linux的一个命令,这个命令就是用来执行脚本程序的。这样运行不需要脚本具有可执行权限。

第三种:bash xx.sh,bash是一个脚本程序解释器,本质上是一个可执行程序。这样执行相当于我们执行了bash程序,然后把xx.sh作为argv[1]传给他运行。

(4)linux下常用的shell解释器有哪些?

sh,bash,dash等.。

二、入门

(1)第一个程序

#!/bin/bash

echo "hello world."

shell中#符号表示注释。shell的第一行比较特殊,一般都会以#!开始来指定使用的shell类型。在linux中,除了bash shell以外,还有很多版本的shell, 例如zsh、dash等等...不过bash shell还是我们使用最多的。

echo是linux中的输出命令,该行的意思很明显的就是输出hello world!

(2)创建文件夹和文件

#!/bin/bash
mkdir test
cd test
touch a.txt
cd ..

通过这个脚本大家可以切实感受到shell编程就是linux命令的逻辑组合而已!!

三、变量和引用

(1)变量定义和初始化。

shell是弱类型语言(语言中的变量如果有明确的类型则属于强类型语言;变量没有明确类型就是弱类型语言),和C语言不同。在shell编程中定义变量不需要制定类型,也没有类型这个概念。

扫描二维码关注公众号,回复: 3608902 查看本文章

(2)变量定义时可以初始化,使用=进行初始化赋值。在shell中赋值的=两边是不能有空格的

(3)变量赋值,变量定义后可以再次赋值,新的赋值会覆盖老的赋值。shell中并不刻意区分变量的定义和赋值,反正每个变量就是一个符号,这个符号的值就是最后一个给他赋值时的值。

(4)变量引用。shell中引用一个变量必须使用$符号,$符号就是变量解引用符号。

注意:$符号后面跟一个字符串,这个字符串就会被当作变量去解析。如果这个字符串本身没有定义,执行时并不会报错,而是把这个变量解析为空。也就是说在shell中没有被定义的变量其实就相当于是一个定义并赋值为空的变量。

注意:变量引用的时候可以$var,也可以${var}。这两种的区别是在某些情况下只能用${var}而不能简单的$var

shell编程中分为两种变量,第一种是我们自己定义的变量(自定义变量),第二种是Linux已定义的环境变量(环境变量, 例如:$PATH, $HOME 等..., 这类变量我们可以直接使用)。

程序实例:

#!/bin/bash

echo $PATH
#自定义变量hello
hello="hello world"
echo $hello

运行结果如下:

book@book-desktop:/mnt/hgfs/share/bash$ source var.sh 
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/work/tools/gcc-3.4.5-glibc-2.3.6/bin
hello world

注意:shell中无引号、单引号和双引号的区别

(1)shell中使用字符串可以不加双引号,直接使用。而且有空格时也可以,但是缺陷是不能输出"或者其他转义字符。

(2)shell中也可以使用单引号来表示字符串,也是直接使用的,不能输出转义字符

(3)单引号中:完全字面替换(不可包含单引号本身)

(4)双引号中:

$加变量名可以取变量的值

反引号仍表示命令替换

\$表示$的字面值 输出$符号

\`表示`的字面值

\"表示"的字面值

\\表示\的字面值

除以上情况之外,在其它字符前面的\无特殊含义,只表示字面值。

四、shell中调用linux命令

(1)直接执行

(2)反引号括起来执行。有时候我们在shell中调用linux命令是为了得到这个命令的返回值(结果值),这时候就适合用一对反引号(键盘上ESC按键下面的那个按键,和~在一个按键上)来调用执行命令。

程序实例:

#!/bin/bash

path=`pwd`
file=`ls`
echo "path = $path"
echo "file  = $file"

执行结果:

book@book-desktop:/mnt/hgfs/share/bash$ source cmd.sh 
path = /mnt/hgfs/share/bash
file  = 2.2.1.hello.sh
2.2.2.shell1.sh
2.2.4.shell2.sh
2.2.5.loop.sh
2.2.6.case.sh
2.2.8.Makefile
2.2.9
b.c
cmd.sh
test
var.sh

五、选择分支

(1)if分支结构

让我们先看一下MAN手册是怎么介绍if命令的:

可以看出,if后面跟着的是一个命令,而不是像其他语言那样返回布尔值(true,false)的表达式。通过MAN手册的介绍我们可以知道:在shell脚本的if其实是根据紧跟后面的那个命令的退出状态码来判断是否执行then后面的语句的。

关于退出状态码,你只需要记住:正常退出(命令执行正常)的状态码是0, 非正常退出的状态码不是0(有不少)。

以上语句的语义为: 如果if后面的命令执行正常(状态码0),那么就执行then后面的语句。否则不执行。 fi代表if语句的结束。

例如:

  
  1 #!/bin/bash
  #这儿由于pwd是linux内置的命令,因此执行后会正常退出(状态码0),所以会执行then中的语句
  #如果此处替换为一个不存在的命令(例如: pw),那么就会非正常退出,不会执行then中的语句
  2 
  3 if pwd
  4 then
  5     echo "OK"
  6 else
  7     echo "error"
  8 fi

程序最终输出OK

那么你可能会问了,我要是就是想像C语言那样判断一个表达式是否成立怎么办呢?客官别着急,有以下两种解决办法:

(1)使用test命令

test EXPRESSION ,test后面跟着的是一个表达式,如果表达式成立,就会退出并返回退出状态码0,否则返回非0。这样,我们就可以借助test命令来实现if对表达式的判断了。一个典型的格式如下:

if  test expression
then
    commands
else 
    commands    
fi

表达式成立就执行then语句,否则else语句。值得注意的是:

test命令只能判断一下三类条件:

  • 数值比较
  • 字符串比较
  • 文件比较
     

数值比较

(-eq)、大于(-gt)、小于(-lt)、大于等于(-ge)、小于等于(-le)

例如:

  1 #!/bin/bash
  2 
  3 num1=10
  4 num2=20
  5 
  6 if test $num1 -gt $num2
  7 then
  8     echo "num1>num2"
  9 else
 10     echo "num1<=num2"
 11 fi
 12 

执行结果:

num1<=num2

字符串比较

注意:这个测试相等只有一个等号

例如:

  1 #!/bib/bash
  2 
  3 str1=test
  4 str2=test
  5 
  6 if test $str1 = $str2
  7 then
  8     echo equal
  9 else
 10     echo "not equal"
 11 fi
 12 

输出结果:

equal

文件比较

文件比较的命令很多,大家可以查看man手册来进行学习,常用的就是 -f ,即判断文件是否存在

(2)使用双括号和双方括号

  • 使用双括号

可以看到使用test命令判断数字逻辑的时候必须符合其命令的规范,需要用到-gt、-eq等,可不可以直接像C语言那样呢?答案是可以的,我们只需要在表达式外边加双括号,但是值得注意的是:括号里面两边都需要有空格,而且(())中变量是可以不使用$来引用的

双括号命令允许你在比较过程中使用高级数学表达式。关键是使用双括号,咱就可以用数学比较符号啦(等于==, 大于>, 小于< 等等都能使用啦)

例1:

  1 #!/bin/bash
  2 
  3 num1=10
  4 num2=20
  5 
  6 if (( num1 == num2 ))
  7 then
  8     echo "num1==num2"
  9 else
 10     echo "num1!=num2"
 11 fi
 12 

输出num1!=num2

例2:

  1 #!/bin/bash
  2 
  3 num1=10
  4 num2=10
  5 
  6 if (( $num1 == $num2 ))
  7 then
  8     echo "num1==num2"
  9 else
 10     echo "num1!=num2"
 11 fi
 12 

输出num1=num2

  • 使用双方括号

双方括号命令提供了针对字符串比较的高级特性。它不仅解决了使用test所带来的一系列毛病,还提供了一些test命令所没有的高级用法。测试相等同样可以使用==。

例1:

  1 #!/bib/bash
  2 
  3 str1=haha
  4 str2=haha
  5 
  6 if [[ $str1 = $str2 ]]
  7 then
  8     echo equal
  9 else
 10     echo "not equal"
 11 fi
 12 

输出equal

例2:

  1 #!/bib/bash
  2 
  3 str1=haha
  4 str2=hahe
  5 
  6 if [[ $str1 = $str2 ]]
  7 then
  8     echo equal
  9 else
 10     echo "not equal"
 11 fi
 12 

输出:not equal

补充:

if判断式中使用“-o”表示逻辑或,“-a”表示逻辑与

相当于C语言中在if后面的条件式中用逻辑与、逻辑或来连接2个式子,最终的if中是否成立取决于2个式子的逻辑运算结果。

(2)case结构

可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。case语句格式如下:

case 值 in
模式1)
    command1
    command2
    ...
    commandN
    ;;
模式2)
    command1
    command2
    ...
    commandN
    ;;
*)
    command1
    command2
    ...
    commandN
    ;;
esac

case工作方式如上所示。取值后面必须为单词in,每一模式必须以右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。

取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。

实例:

  1 #!/bin/bash
  2 num=2
  3 case $num in
  4 1)
  5     echo "num=1";;
  6 2)
  7     echo "num=2";;
  8 3)
  9     echo "num=3";;
 10 4)
 11     echo "num=4";;
 12 *)
 13     echo "defaul";;
 14 esac  

输出:

num=2

Ref:

https://www.cnblogs.com/dongying/p/6262935.html

https://blog.csdn.net/a5nan/article/details/53079591

猜你喜欢

转载自blog.csdn.net/wwwlyj123321/article/details/81624634