当前位置:   article > 正文

项目实训(树莓派)(十五)树莓派4B下的ubuntu系统下的Bash的使用和脚本初步-第一部分(变量 脚本 字符串等)

项目实训(树莓派)(十五)树莓派4B下的ubuntu系统下的Bash的使用和脚本初步-第一部分(变量 脚本 字符串等)

目录

Bash介绍

实验目的

实验环境

实验步骤与内容:

1.编写并执行第一个Bash脚本

2.Bash变量

3.Bash字符串

4.Bash数组

5.Bash注释

6.Bash传递参数


Bash介绍

Bash是一个命令处理器,通常运行于文本窗口中,并能执行用户直接输入的命令。Bash还能从文件中读取命令,这样的文件称为脚本。和其他Unix shell 一样,它支持文件名替换(通配符匹配)、管道here文档、命令替换、变量,以及条件判断和循环遍历的结构控制语句。

Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。

Bash,也就是 Bourne Again Shell,由于易用和免费,Bash 在日常工作中被广泛使用。同时,Bash 也是大多数Linux 系统默认的 Shell。

在一般情况下,人们并不区分 Bourne Shell 和 Bourne Again Shell,所以,像 #!/bin/sh,它同样也可以改为 #!/bin/bash

实验目的

掌握Bash命令处理器的使用

实验环境

树莓派4B、系统:Ubuntu 20.10系统 、vim软件

实验步骤与内容:

1.编写并执行第一个Bash脚本

打开终端,通过vim命令来创建文件,新建一个文件test.sh,扩展名为sh(sh代表shell),扩展名并不会影响脚本的执行,如果使用python来写shell脚本,扩展名使用py就好了。

在vim编辑器中输入下面的代码:

  1. #!/bin/bash
  2. #This is a example
  3. echo "Hello World !"

这样我们第一个Bash程序就写完了。接下来解释一下这个简单的程序:

(1)第一行的 #! 和/bin/bash是什么意思

#! 是说明 test 这个文件的类型的,有点像 Windows 系统下用不同文件后缀来表示不同文件类型的意思(但不是完全相同)。Linux 系统根据 "#!" 及该字串后面的信息确定该文件的类型,关于这一问题同学们回去以后可以通过 "man magic"命令 及 /usr/share/magic 文件来了解这方面的更多内容。

在 BASH 中 第一行的 "#!" 及后面的 "/bin/bash" 就表明该文件是一个 BASH 程序,需要由 /bin 目录下的 bash 程序来解释执行。BASH 这个程序一般是存放在 /bin 目录下,如果你的 Linux 系统比较特别,bash 也有可能被存放在 /sbin 、/usr/local/bin 、/usr/bin 、/usr/sbin 或 /usr/local/sbin 这样的目录下;如果还找不到,你可以用 "locate bash" "find / -name bash 2> /dev/null" 或 "whereis bash" 这三个命令找出 bash 所在的位置;如果仍然找不到,那你可能需要自己动手安装一个BASH 软件包了。
(2)第二行是注释吗 

第二行的 "# This is a example" 就是 BASH 程序的注释,在 BASH 程序中从“#”号(注意:后面紧接着是“!”号的除外)开始到行尾的多有部分均被看作是程序的注释。
(3)echo 语句

第三行的echo语句的功能就是把echo 后面的字符串输出到标准输出中去。由于 echo 后跟的是 "Hello World" 这个字符串,因此 "Hello World"这个字串就被显示在控制台终端的屏幕上了。需要注意的是 BASH 中的绝大多数语句结尾处都没有分号。

接下来就是运行这个Bash脚本,一共有两种办法:

1.作为可执行程序

将上面的文件保存为test.sh,并通过命令行移动到相应的目录之下,之后输入以下命令:

  1. $ chmod +x ./test.sh #使得该脚本具有执行的权限
  2. $ ./test.sh #执行脚本

注意,这里一定要写成 ./test.sh,而不是 test.sh,运行其它二进制的程序也一样,直接写 test.sh,linux 系统会去 PATH 里寻找有没有叫 test.sh 的,而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 里,你的当前目录通常不在 PATH 里,所以写成 test.sh 是会找不到命令的,要用 ./test.sh 告诉系统说,就在当前目录找。

执行结果如下:

2.作为解释器参数

这种运行方式是,直接运行解释器,其参数就是 shell 脚本的文件名,如:

  1. $ /bin/sh test.sh 或者
  2. $ bash test.sh

执行结果如下:

这是由于 hello 文件第一行的 "#! /bin/bash" 的作用,系统会自动用/bin/bash 程序去解释执行 hello 文件的。

需要注意的是,BASH 程序被执行后,实际上 Linux 系统是另外开设了一个进程来运行的。

2.Bash变量

接下来我们就先看看Bash中的变量是如何定义和使用的。

定义变量时,变量名不加美元符号($,PHP语言中变量需要),如:

my_name="shumeipai"

注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。同时,变量名的命名须遵循如下规则:

  • 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
  • 中间不能有空格,可以使用下划线(_)。
  • 不能使用标点符号。
  • 不能使用bash里的关键字(可用help命令查看保留关键字)。

以下举例一些有效的Shell变量名:

  1. zhonghua
  2. _shumeipai
  3. sdu6
  4. SDU

无效的变量命名:

  1. v ar=123
  2. use?name=hh

除了显式的直接进行赋值,还可以用语句来给变量赋值,例如:

  1. for file in 'ls Documents'
  2. for file in $(ls Documents)

上述语句可以将Documents目录下的文件名循环打印下来。

使用变量

使用一个定义过的变量,只需要在变量名之前加上美元符号即可,例如:

  1. zhonghua="China"
  2. echo $zhonghua
  3. echo ${zhonghua}

变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:

  1. for hobby in swim pingpang football Java; do
  2. echo "I am good at ${hobby}."
  3. done

如果不给skill变量加花括号,写成echo "I am good at $skillScript",解释器就会把$skillScript当成一个变量(其值为空),代码执行结果就不是我们期望的样子了。所以我推荐给所有变量加上花括号,这是个好的编程习惯。

已定义的变量,可以被重新定义,如:

  1. your_name="tom"
  2. echo $your_name
  3. your_name="alibaba"
  4. echo $your_name

注意,第二次赋值的时候不能写$your_name="alibaba",使用变量的时候才加美元符($)。

只读变量

使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。

下面的例子尝试更改只读变量,结果报错:

  1. #!/bin/bash
  2. myname="China"
  3. readonly myname
  4. myUrl="America"

运行脚本,执行结果如下:

/bin/sh: NAME: This variable is read only.

删除变量

使用 unset 命令可以删除变量。语法:

unset variable_name

变量被删除后不能再次使用。unset 命令不能删除只读变量

示例:

  1. #!/bin/sh
  2. myname="China"
  3. unset myname
  4. echo $myname

执行此脚本将没有任何输出。

变量类型

执行Bash脚本时,会同时产生三种变量:

第一种:局部变量 局部变量在脚本或命令中定义,仅在当前Bash实例中有效,其他Bash启动的程序不能访问局部变量。

第二种:环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候Bash脚本也可以定义环境变量。

第三种:Bash变量 Bash变量是由Bash程序设置的特殊变量。Bash变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了Bash脚本的正常运行

3.Bash字符串

字符串是Bash编程中最常用最有用的数据类型,字符串可以用单引号,也可以用双引号,也可以不用引号。

单引号声明字符串

str='string'

单引号声明字符串的一些限制:

  • 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
  • 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。

 双引号声明字符串

  1. your_name='China'
  2. str="Hello, I know you are \"$your_name\"! \n"
  3. echo -e $str

输出结果为:

Hello, I know you are "China"! 

双引号的优点:

  • 双引号里可以有变量
  • 双引号里可以出现转义字符

字符串的拼接

  1. your_name="China"
  2. # 使用双引号拼接
  3. greeting="hello, "$your_name" !"
  4. greeting_1="hello, ${your_name} !"
  5. echo $greeting $greeting_1
  6. # 使用单引号拼接
  7. greeting_2='hello, '$your_name' !'
  8. greeting_3='hello, ${your_name} !'
  9. echo $greeting_2 $greeting_3

输出结果:

  1. hello, runoob ! hello, China !
  2. hello, runoob ! hello, ${your_name} !

通过上述结果可以看出字符串是可以拼接的,单引号内不可以使用已经存在的变量,双引号可以使用其他的变量。
获取字符串长度

  1. string="abcd"
  2. echo ${#string}

输出:

4

在花括号内使用#可以输出字符串的长度

提取子字符串

以下示例提取从字符串的第3个字符开始截取3个字符:

  1. string="China is very good"
  2. echo ${string:2:3}

输出:

ina

注意:字符串的第一个字符的索引值为0。所以第三个字符所对应的索引值为2。

查找子字符串

 示例:查找字符串中字符h或者a出现的位置(哪一个出现的早就返回哪一个的位置)

  1. string="China"
  2. echo `expr index "$string" ha`

输出:

注意:上述代码中`是反引号,并不是单引号'。这时候所输出的值并不是索引值了,而是字符串真正的位置。

字符串截取:

Linux 的字符串截取很有用。有八种方法。

假设有变量 var=http://www.aaa.com/123.htm

1. # 号截取,删除左边字符,保留右边字符。

echo ${var#*//}

其中 var 是变量名,# 号是运算符,*// 表示从左边开始删除第一个 // 号及左边的所有字符

即删除 http://

结果是 :www.aaa.com/123.htm

2. ## 号截取,删除左边字符,保留右边字符。

echo ${var##*/}

##*/ 表示从左边开始删除最后(最右边)一个 / 号及左边的所有字符

即删除 http://www.aaa.com/

结果是 123.htm

3. %号截取,删除右边字符,保留左边字符

echo ${var%/*}

%/* 表示从右边开始,删除第一个 / 号及右边的字符

结果是:http://www.aaa.com

4. %% 号截取,删除右边字符,保留左边字符

echo ${var%%/*}

%%/* 表示从右边开始,删除最后(最左边)一个 / 号及右边的字符

结果是:http:

5. 从左边第几个字符开始,及字符的个数

echo ${var:0:5}

其中的 0 表示左边第一个字符开始,5 表示字符的总个数。

结果是:http:

6. 从左边第几个字符开始,一直到结束。

echo ${var:7}

其中的 7 表示左边第8个字符开始,一直到结束。

结果是 :www.aaa.com/123.htm

7. 从右边第几个字符开始,及字符的个数

echo ${var:0-7:3}

其中的 0-7 表示右边算起第七个字符开始,3 表示字符的个数。

结果是:123

8. 从右边第几个字符开始,一直到结束。

echo ${var:0-7}

表示从右边第七个字符开始,一直到结束。

结果是:123.htm

注:(左边的第一个字符是用 0 表示,右边的第一个字符用 0-1 表示)

总结一下就是:

#、## 表示从左边开始删除。一个 # 表示从左边删除到第一个指定的字符;两个 # 表示从左边删除到最后一个指定的字符。

%、%% 表示从右边开始删除。一个 % 表示从右边删除到第一个指定的字符;两个 % 表示从左边删除到最后一个指定的字符。

删除包括了指定的字符本身。

4.Bash数组

bash支持一维数组(不支持多维数组),并且没有限定数组的大小。

类似于 C 语言,数组元素的下标由 0 开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0。

定义一个数组

在 Bash 中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为:

array_name=(value0 value1 value2 value3)

或:

  1. array_name=(
  2. value0
  3. value1
  4. value2
  5. value3
  6. )

还可以单独定义数组的各个分量:

  1. array_name[0]=value0
  2. array_name[1]=value1
  3. array_name[n]=valuen

可以不使用连续的下标,而且下标的范围没有限制。

读取数组

读取数组元素值的一般格式是:

${数组名[下标]}

例如:

valuen=${array_name[n]}

示例:

  1. #!/bin/bash
  2. my_array=(A B "C" D)
  3. echo "第一个元素为: ${my_array[0]}"
  4. echo "第二个元素为: ${my_array[1]}"
  5. echo "第三个元素为: ${my_array[2]}"
  6. echo "第四个元素为: ${my_array[3]}"

 执行脚本,输出结果为:

  1. $ chmod +x test.sh
  2. $ ./test.sh
  3. 第一个元素为: A
  4. 第二个元素为: B
  5. 第三个元素为: C
  6. 第四个元素为: D

获取数组中全部的元素:

使用@ 或 * 可以获取数组中的所有元素,例如:

echo ${array_name[@]}

 示例:

  1. #!/bin/bash
  2. my_array[0]=A
  3. my_array[1]=B
  4. my_array[2]=C
  5. my_array[3]=D
  6. echo "数组的元素为: ${my_array[*]}"
  7. echo "数组的元素为: ${my_array[@]}"

输出结果为:

  1. $ chmod +x test.sh
  2. $ ./test.sh
  3. 数组的元素为: A B C D
  4. 数组的元素为: A B C D

获取数组的长度

获取数组长度的方法与获取字符串长度的方法相同,例如:

  1. # 取得数组元素的个数
  2. length=${#array_name[@]}
  3. # 或者
  4. length=${#array_name[*]}
  5. # 取得数组单个元素的长度
  6. lengthn=${#array_name[n]}

 数组的值也可以写入变量。

示例:

  1. A=1
  2. my_array=($A B C D)
  3. echo "first: ${my_array[0]}"
  4. echo "second: ${my_array[1]}"
  5. echo "third: ${my_array[2]}"
  6. echo "four: ${my_array[3]}"

输出结果为:

first: 1 second: B third: C four: D

循环遍历数组的多种写法:

  1. #!/bin/bash
  2. my_arry=(e f "g","h" abc)
  3. echo "-------FOR循环遍历输出数组--------"
  4. for i in ${my_arry[@]};
  5. do
  6. echo $i
  7. done
  8. echo "-------::::WHILE循环输出 使用 let i++ 自增:::::---------"
  9. j=0
  10. while [ $j -lt ${#my_arry[@]} ]
  11. do
  12. echo ${my_arry[$j]}
  13. let j++
  14. done
  15. echo "--------:::WHILE循环输出 使用 let "n++ "自增: 多了双引号,其实不用也可以:::---------"
  16. n=0
  17. while [ $n -lt ${#my_arry[@]} ]
  18. do
  19. echo ${my_arry[$n]}
  20. let "n++"
  21. done
  22. echo "---------::::WHILE循环输出 使用 let m+=1 自增,这种写法其他编程中也常用::::----------"
  23. m=0
  24. while [ $m -lt ${#my_arry[@]} ]
  25. do
  26. echo ${my_arry[$m]}
  27. let m+=1
  28. done
  29. echo "-------::WHILE循环输出 使用 a=$[$a+1] 自增,个人觉得这种写法比较麻烦::::----------"
  30. a=0
  31. while [ $a -lt ${#my_arry[@]} ]
  32. do
  33. echo ${my_arry[$a]}
  34. a=$[$a+1]
  35. done

字符串转数组:

  1. #!/bin/bash
  2. words="ii dd kk"
  3. #字符串转数组,空格是分隔符
  4. array=(${words// / })
  5. #打印数组最后一个成员
  6. echo ${array[${#array[*]}-1]}
  7. #打印数组长度
  8. echo ${#array[*]}
  9. #字符串不转换为数组,在循环实现以空格为分隔符打印每个成员
  10. for word in ${words}; do
  11. echo ${word}
  12. done

结果如下:

kk2iiddkk

5.Bash注释

以 # 开头的行就是注释,会被解释器忽略。

通过每一行加一个 # 号设置多行注释,像这样:

  1. #--------------------------------------------
  2. # 这是一个注释
  3. # author:ubuntu
  4. #--------------------------------------------

如果在开发过程中,遇到大段的代码需要临时注释起来,过一会儿又取消注释,怎么办呢?

每一行加个#符号太费力了,可以把这一段要注释的代码用一对花括号括起来,定义成一个函数,没有地方调用这个函数,这块代码就不会执行,达到了和注释一样的效果。

多行注释

多行注释还可以使用以下格式:

  1. :<<EOF
  2. 注释内容...
  3. 注释内容...
  4. 注释内容...
  5. EOF
  6. :<<'
  7. 注释内容...
  8. 注释内容...
  9. 注释内容...
  10. '
  11. :<<!
  12. 注释内容...
  13. 注释内容...
  14. 注释内容...
  15. !

6.Bash传递参数

我们可以在执行Bash脚本时,向脚本传递参数,脚本内获取参数的格式为:$nn 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推即可

示例:

以下实例我们向脚本传递三个参数,并分别输出,其中 $0 为执行的文件名(包含文件路径):

  1. #!/bin/bash
  2. echo "Shell 传递参数实例!";
  3. echo "执行的文件名:$0";
  4. echo "第一个参数为:$1";
  5. echo "第二个参数为:$2";
  6. echo "第三个参数为:$3";

为脚本设置可执行权限,并执行脚本,输出结果如下所示:

  1. $ chmod +x test.sh
  2. $ ./test.sh 1 2 3
  3. Shell 传递参数实例!
  4. 执行的文件名:./test.sh
  5. 第一个参数为:1
  6. 第二个参数为:2
  7. 第三个参数为:3

 另外,还有几个特殊字符用来处理参数:

参数功能说明
$#传递到脚本的参数个数
$*以一个单字符串显示所有向脚本传递的参数。
如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
$$脚本运行的当前进程ID号
$!后台运行的最后一个进程的ID号
$@与$*相同,但是使用时加引号,并在引号中返回每个参数。
如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。
$-显示Shell使用的当前选项,与set命令功能相同。
$?显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
  1. #!/bin/bash
  2. echo "Shell 传递参数实例!";
  3. echo "第一个参数为:$1";
  4. echo "参数个数为:$#";
  5. echo "传递的参数作为一个字符串显示:$*";

执行脚本,输出结果:

  1. $ chmod +x test.sh
  2. $ ./test.sh 1 2 3
  3. Shell 传递参数实例!
  4. 第一个参数为:1
  5. 参数个数为:3
  6. 传递的参数作为一个字符串显示:1 2 3

$* 与 $@ 区别:

  • 相同点:都是引用所有参数。
  • 不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)。
  1. #!/bin/bash
  2. echo "-- \$* 演示 ---"
  3. for i in "$*"; do
  4. echo $i
  5. done
  6. echo "-- \$@ 演示 ---"
  7. for i in "$@"; do
  8. echo $i
  9. done

输出:

  1. $ chmod +x test.sh
  2. $ ./test.sh 1 2 3
  3. -- $* 演示 ---
  4. 1 2 3
  5. -- $@ 演示 ---
  6. 1
  7. 2
  8. 3

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/190330
推荐阅读
相关标签
  

闽ICP备14008679号