Shell脚本入门

一、shell介绍

1、shell是操作系统的终端命令行

(1)shell可以理解为软件系统提供给用户操作的命令行界面,可以说它是人机交互的一种方式。

(2)我们可以使用shell操作系统、uboot等软件系统进行交互。具体来说就是我们通过shell给软件系统输入命令然后回车执行,执行完成后又会回到shell命令行可以再次输入命令执行。

(3)上述的操作方式一般情况下工作很好,但是有缺陷。

  譬如我们要在linux下创建一个文件a.c,可以touch a.c 但是如果我现在是用在linux下创建100个文件,分别为a1.c a2.c…a100.c 如果这时候还是手工去命令行下执行命令创建也可以,但是很累。

  最好的做法就是把创建过程写成一个shell脚本程序,然后去执行这个shell脚本程序,执行这个程序的效果和手工在命令行输入那些命令效果一样的。

2、shell是一类编程语言

(1)编写shell脚本时使用的语言就是shell语言,又叫脚本语言。

(2)shell脚本其实是一类语言而不是一个语言。

3、常用shell语言:sh、bash、csh、ksh、perl、python等

(1)在linux下常用的脚本语言其实就是bash、sh;

(2)perl、python这样的高级shell脚本语言,常用在网络管理配置等领域,系统运维人员一般要学习这些。

(3)脚本语言一般在嵌入式中:主要是用来做配置。(一个复杂的嵌入式程序都是可配置的,配置过程就是用脚本语言来实现的)自然不会使用过于复杂的脚本语言特性,因此只需要针对性的学习即可。

(4)linux下最常用的脚本就是bash,我们学习也是以bash为主。

4、shell脚本的运行机制:解释运行

(1)C语言(C++)这种编写过程是:编写出源代码(源代码是不能直接运行的)然后编译链接形成可执行二进制程序,然后才能运行;而脚本程序不同,脚本程序编写好后源代码即可直接运行(没有编译链接过程)

(2)shell程序是解释运行的,所谓解释运行就是说当我们执行一个shell程序时,shell解析器会逐行的解释shell程序代码,然后一行一行的去运行(顺序结构)。

(3)CPU实际只认识二进制代码,根本不认识源代码。

  脚本程序源代码其实也不是二进制代码,CPU也不认识,也不能直接执行。

  只不过脚本程序的编译链接过程不是以脚本程序源代码为单位进行的,而是在脚本运行过程中逐行的解释执行时才去完成脚本程序源代码转成二进制的过程(不一定是编译链接,因为这行脚本程序可能早就编译连接好了,这里我们只是调用它)的。

二、动手写第一个shell

1、编辑器、编译器、运行方法(脚本的3种执行方法)

(1)shell程序是文本格式的,只要是文本编辑器都可以。

  但是因为我们的shell是要在linux系统下运行的,所以换行符必须是’\n’,而windows下的换行符是"\r\n",因此windows中的编辑器写的shell不能在linux下运行。所以本文章示例都是在linux下使用vi编辑器(实际上是vim)进行编写调试的。

(2)编译器 不涉及,因为shell是解释性语言,直接编辑完就可以运行。

(3)shell程序运行的运行有多种方法,这里介绍三种方法:

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

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

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

解释器:python等可能需要安装,对于bash ,Linux系统提供了

2、hello world程序和解释

#!/bin/bash
echo "Hello World !"

(1)shell程序的第一行一般都是: #!/bin/sh

  这行话以#!开始,后面加上一个pathname,这行话的意思就是指定shell程序执行时被哪个解释器解释执行。所以我们这里写上/bin/sh意思就是这个shell将来被当前机器中/bin目录下的sh可执行程序执行。

  可以将第一行写为:#!/bin/bash来指定使用bash执行该脚本。

  注意:在ubuntu上面默认使用的解释器其实不是bash,而是dash。dash是ubuntu中默认使用的脚本解释器。

(2)脚本中的注释使用#,#开头的行是注释行。如果有多行需要注释,每行前面都要加#。(#就相当于是C语言中的//)

(3)shell程序的正文,由很多行shell语句构成。

3、shell并不神秘

(1)shell就是把以前命令行中键入执行的命令写成了程序。shell其实就是为了避免反复的在命令行下手工输入而发明的一种把手工输入步骤记录下来,然后通过执行shell脚本程序就能再次复述原来记录的手工输入过程的一种技术。

(2)shell编辑完可以直接运行(不需编译),解释运行,类似于python

三、shell编程学习

1、shell中使用linux命

当前目录下创建文件夹dir,dir下创建文件b.txt

#!/bin/sh
mkdir test
cd test
touch a.txt
echo "test" >> a.txt #将test输入到a.txt文件
cd ../

2、shell中的变量定义和引用

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

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

注意:shell对语法非常在意,非常严格。很多地方空格都是必须没有或者必须有,而且不能随意有没有空格。

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

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

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

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

示例如下:
for skill in Ada Coffe Action Java; do
    echo "I am good at ${skill}Script"
done
如果不给skill变量加花括号,写成echo "I am good at $skillScript",解释器就会
把$skillScript当成一个变量(其值为空),代码执行结果就不是我们期望的样子了。

3、shell中无引用、单引号和双引号的区别

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

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

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

(4)双引号中:

$加变量名可以取变量的值
反引号仍表示命令替换
\$表示$的字面值			输出$符号
\`表示`的字面值
\"表示"的字面值
\\表示\的字面值
除以上情况之外,在其它字符前面的\无特殊含义,只表示字面值。

4、shell中调用linux命令

(1)直接执行

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

5、shell中的选择分支结构

(1)shell的if语言用法很多,在此只介绍常用的,其他感兴趣可以自己去学
(2)典型if语言格式

if [表达式]; then
	xxx
	yyy
	zzz
else
	xxx
	ddd
	uuu
fi

(3)if的典型应用

判断文件是否存在。(-f),注意[]里面前后都有空格,不能省略。

判断目录是否存在  (-d)

判断字符串是否相等("str1" = "str2"),注意用一个等号而不是两个

判断数字是否相等(-eq)、大于(-gt)、小于(-lt)、大于等于(-ge)、小于等于(-le)	
(eq就是equal,gt就是greater than,lt就是less than,ge就是greater or equal,
le就是less or equal)

判断字符串是否为空(-z)注意-z判断时如果变量本身没定义也是不成立(也就是说-z认为没定
义不等于为空)

(4)if判断式中使用“-o”表示逻辑或
  相当于C语言中在if后面的条件式中用逻辑与、逻辑或来连接2个式子,最终的if中是否成立取决于2个式子的逻辑运算结果。

(5)逻辑与&&和逻辑或||与简写的if表达式相结合

a=10
b=20
if [ $a == $b ]
then
   echo "a 等于 b"
elif [ $a -gt $b ]
then
   echo "a 大于 b"
elif [ $a -lt $b ]
then
   echo "a 小于 b"
else
   echo "没有符合的条件"
fi

6、shell中的循环结构

	break 命令允许跳出所有循环(终止执行后面的所有循环)

	continue 命令与 break 命令类似,只有一点差别,它不会跳出所有循环,仅仅
跳出当前循环。

(1)for循环
  要求:能看懂、能改即可。不要求能够完全不参考写出来。因为毕竟嵌入式并不需要完全重新手写shell,系统管理员(服务器运维人员,应用层系统级管理开发的才需要完全掌握shell)

for var in item1 item2 ... itemN
do
    command1
    command2
    ...
    command
done

写成一行:
for var in item1 item2 ... itemN; do command1; command2… done;
for loop in 1 2 3 4 5
do
    echo "The value is: $loop"
done

输出结果:
The value is: 1
The value is: 2
The value is: 3
The value is: 4
The value is: 5

(2)while循环
  和C语言的循环在逻辑上无差别

  要注意很多格式要求,譬如:while后面的[]两边都有空格,[]后面有分号分号(如果do放在一行的话),i++的写法中有两层括号

while condition
do
    command
done

无限循环:
while :
do
    command
done
或者

while true
do
    command
done
或者

for (( ; ; ))
echo '按下 <CTRL-D> 退出'
echo -n '输入你最喜欢的网站名: '
while read FILM
do
    echo "是的!$FILM 是一个好网站"
done
运行脚本,输出类似下面:

按下 <CTRL-D> 退出
输入你最喜欢的网站名:菜鸟教程
是的!菜鸟教程 是一个好网站

四、shell中其他值得关注的知识点

1、echo的创建和追加输入文件

(1)在shell中可以直接使用echo指令新建一个文件,并且将一些内容传入这个文件中。创建文件并输入内容的关键就是>。

(2)还可以使用echo指令配合追加符号>> 向一个已经存在的文件末尾追加输入内容。

2、case语句

(1)shell中的case语句和C语言中的switch case语句作用一样,格式有差异

(2)shell中的case语句天生没有break,也不需要break,和C语言中的switch case不同。shell中的case默认就是匹配上哪个执行哪个,不会说执行完了还去执行后面的其他case(就好像shell中的case语言默认都带了break)。

case 值 in
模式1)
    command1
    command2
    ...
    commandN
    ;;
模式2)
    command1
    command2
    ...
    commandN
    ;;
esac
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
    1)  echo '你选择了 1'
    ;;
    2)  echo '你选择了 2'
    ;;
    3)  echo '你选择了 3'
    ;;
    4)  echo '你选择了 4'
    ;;
    *)  echo '你没有输入 1 到 4 之间的数字'
    ;;
esac
输入不同的内容,会有不同的结果,例如:

输入 1 到 4 之间的数字:
你输入的数字为:
3
你选择了 3

3、调用shell程序的传参

(1)C语言中可以通过main函数的argc和argv给程序传参

(2)shell程序本身也可以在调用时传参给他。在shell程序内部使用传参也是使用的一些特定符号来表示的,包括:

$#表示调用该shell时传参的个数。($#计数时只考虑真正的参数个数)
$0$1$2·····则依次表示传参的各个参数。
C语言:./a.out aa bb cc 	argc = 4, argv[0] = ./a.out, argv[1]是第一个有效参数

shell:source a.sh aa bb cc  $# = 3, $0是执行这个shell程序的解析程序的名字,
$1是第一个有效参数的值,$2是第2个有效参数的值·····
#!/bin/bash

echo "Shell 传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";

为脚本设置可执行权限,并执行脚本,输出结果如下所示:
$ chmod +x test.sh 
$ ./test.sh 1 2 3
Shell 传递参数实例!
执行的文件名:./test.sh
第一个参数为:1
第二个参数为:2
第三个参数为:3

注意:shell中的很多语法特性和C语言中是相同的,也有很多是不同的。所以大家学的越多越容易混淆(本质原因还是用的不熟悉,用的少),解决方案是:做笔记、作总结、多写代码经常用

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

4、while循环和case语言和传参结合

(1)shell中的break关键字和C语言中意义相同(都是跳出)但是用法不同。因为shell中case语句默认不用break的,因此在shell中break只用于循环跳出。所以当while中内嵌case语句时,case中的break是跳出外层的while循环的,不是用来跳出case语句的。

运算符	 说明	               举例
&&	   逻辑的 AND	 [[ $a -lt 100 && $b -gt 100 ]] 返回 false
||	   逻辑的 OR	     [[ $a -lt 100 || $b -gt 100 ]] 返回 true

!	非运算,表达式为 true 则返回 false,否则返回 true。[ ! false ] 返回 true。
-o	或运算,有一个表达式为 true 则返回 true。	[ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a	与运算,两个表达式都为 true 才返回 true。	[ $a -lt 20 -a $b -gt 100 ] 返回 false。

(2)shell中的$# $1等内置变量的值不是不可变的,而是可以被改变,被shift指令改变。shift指令有点像左移运算符,把我们给shell程序的传参左移了一个移出去了,原来的$2变成了新的$1,原来的 $#少了1个。

注:本资料大部分由朱老师物联网大讲堂课程笔记整理而来并且引用了部分他人博客的内容,如有侵权,联系删除!水平有限,如有错误,欢迎各位在评论区交流。

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小嵌同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值