欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

shell编程入门(bash)

程序员文章站 2022-03-13 17:25:00
...

一、背景知识

(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编程中定义变量不需要制定类型,也没有类型这个概念。

(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

运行结果如下:

aaa@qq.com:/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"

执行结果:

aaa@qq.com:/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命令的:

shell编程入门(bash)

可以看出,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命令只能判断一下三类条件:

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

数值比较

shell编程入门(bash)

(-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

 

字符串比较

shell编程入门(bash)

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

例如:

  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

相关标签: ARM