Shell脚本基础—编写脚本会遇到的各种问题

首先我们先理解一下 Shell bash Shell脚本的概念:

1. Shell & bash

   bash其实就是Shell的一种

2. Shell & Shell脚本

   1. 两者是不同的概念;Shell是命令行解释器

   2. Shell脚本(shell script),是一种为Shell编写的脚本程序

   3. 在业界,所说的Shell就是Shell脚本;
      我们统一认为“Shell编程”都是指的是“Shell脚本编程”

Shell脚本的格式:


1. 第一行:#!/bin/bash

   其中#!就是一个约定的标记,用于告诉系统这个脚本需要什么解释器来执行 
   (/bin/bash就是这个解释器的路径);#!的名称通常叫做:"Shebang"或者"Sha-bang"

 2. 除了第一行的 # ,其他行都可以用 # 来注释该行,相当于C语言中的 //  

 3. 等式两边禁止有空格

   eg: 正确写法:a=10  

 4. 同样的每行写完不用用 ; 来区分行号

写一个简单的Shell脚本:


一般情况下,在创建一个多个文件的时候,我们需要在命令行一直输入命令,然而下次如果还有同样的操作,会很麻烦,比如:
Shell脚本基础—编写脚本会遇到的各种问题_第1张图片
上面的rm -rf file*的意思就是:删除所有带file的文件

而如何去用Shell脚本去实现这个命令呢?
这里写图片描述

#!/bin/bash

touch file1
touch file2
touch file3
touch file4
touch file5
touch file6
touch file7
touch file8

执行Shell脚本的两种方式:

方式一 : 

      bash ./first.sh

      其中bash是一个解释器,后面后详细介绍Shell脚本的执行过程

方式二 : 

      chmod +x first.sh
      ./first.sh

      这种方式就是给脚本加了一个可执行权限(X 就是表示可执行权限)

这里写图片描述
这里写图片描述

一个奇怪的现象:

#!/bin/bash

pwd
cd ..
pwd

按照上面的思路,上面的执行结果就是:
1. 显示当前的路径
2. 返回上一层
3. 再显示当前的路径(也就是上一层的路径)

Shell脚本基础—编写脚本会遇到的各种问题_第2张图片

结果:
这里写图片描述
路径是对的,可是执行之后,并没有返回上一层,这是什么情况?

下面就来介绍一下内置命令的概念以及Shell脚本执行的过程:

内置命令 &Shell特点 & Shell脚本的执行过程:


1. 内置命令:

如上的:  cd ..

还有 : export echo 

2. Shell特点:

1. 解释非编译型
2. 弱类型
3. 执行模式:交互式/批处理式

   这里的弱类式的意思就是:变量类型不太会说明,不像C语言中有:char int string...

3. Shell脚本的执行过程:

首先,我们都知道: 一个可执行的程序,是二进制,而这里是一个文本,那是怎么运行的?

#!/bin/bash

pwd
cd ..
pwd


一: 执行:bash ./test1.sh 后的过程 :

1. 当前进程会fork(),子进程调用exec,然后将#!后面的解释器bash程序的代码替换当前进程 

2. 上面解释器的代码已经替换了子进程,下来就是一一去处理文本中的命令

3. 子进程再去fork(),让孙子进程去处理第一行的命令

   将第一行命令作为参数传给解释器(当前的解释器就类似于"函数"4. 上面只是处理了一行的命令,如果还有命令行,再去fork()



二 :从上面的执行过程,我们就可以知道,为什么会出现上面的奇怪现象?

    因为:
        上面的 cd.. 是在 子bash 中处理的,而对 父bash 没有影响

4. 如何处理内置命令这种问题?

不准 父bash 创建子进程处理这个内置命令, 父bash 自己处理

方式一: 

      用 . 修饰脚本

方式二: 

      用 source 修饰脚本

方式一:

这里写图片描述

方式二:

这里写图片描述

赋值和命名规则


1. 赋值和命名规则

变量名命名的规则 :

   1. 首个字符必须为字母(a-z 或者 A-Z)

   2. 中间不能有空格,可以使用下划线()

   3. 不能使用标点符号

   4. 不能使用bash中的关键字(可以通过help命令来查看关键字) 

2. 使用一个赋过值的变量,给变量前加 $ :

Shell脚本基础—编写脚本会遇到的各种问题_第3张图片

vim test2.sh:

#!/bin/bash

myint=22
mychar=c
myfloat=3.15
mystring="hello Shell"

echo $myint
echo $mychar
echo $myfloat
echo $mystring

Shell脚本基础—编写脚本会遇到的各种问题_第4张图片

而如果要实现赋过值的变量和一个字符串拼接,应该在变量名外面加上{ },为了让解释器更好的识别变量边界:

Shell脚本基础—编写脚本会遇到的各种问题_第5张图片

 由上图我们可以看出:

 1.  实现两个赋过值的变量拼接:
        $a$b 
       直接将两个变量拼接在一起

 2.  实现一个赋过值的变量和字符串拼接:

     给变量外边加上花括号{};用来区分边界

 3. 如果不加花括号,则会将变量和紧挨着的字符串一起当做一个新的变量 
    这样输出的结果就为空

Shell脚本基础—编写脚本会遇到的各种问题_第6张图片

3. 只读变量 & 删除变量


只读变量:使用readonly修饰变量
#!/bin/bash

readonly mystr="hello"
echo $mystr
mystr=world
echo $mystr

Shell脚本基础—编写脚本会遇到的各种问题_第7张图片

删除变量:使用unset命令

Shell脚本基础—编写脚本会遇到的各种问题_第8张图片
而只读变量是不能被删除的!
Shell脚本基础—编写脚本会遇到的各种问题_第9张图片

4. 变量类型 :


Shell变量是弱类型,而这里的变量类型和C语言的变量类型是不一样的

1. 本地变量

   简单的来说:本地变量就好比是C语言中的局部变量  
             只在当前的Shell实例中有效,其他的程序无效 

2. 环境变量

    类似于C语言中的全局变量
    在所有的程序中都有效
    命令:export 环境变量

3. Shell变量

   意思就是Shell脚本中的变量
   有两种 :本地变量
           环境变量

下面通过例子来证明:
Shell脚本基础—编写脚本会遇到的各种问题_第10张图片

5. 获取字符串的长度 & 提取子字符串 :

Shell脚本基础—编写脚本会遇到的各种问题_第11张图片

#!/bin/bash

mystring=abcde12345

echo ${#mystring} # 获取字符串的长度

echo ${mystring:1:4} # 从字符串第2个字符开始截取4个字符
echo ${mystring:2:5} # 从字符串第3个字符开始截取5个字符
[root@localhost Shell]# bash test5.sh
10
bcde
cde12



1. ${#变量名} : 表示获取变量的字符串长度

2. ${mystring:2:5} ${mystring:1:4}: 表示从某个字符开始(下标)截取5个或者4个字符  
                                 (后面的表示字符的个数而不是结束位置的下标)

6. 通配符 :

1. * :匹配0个或多个任意字符
2. ? : 匹配一个任意字符
3. [ ] :匹配一个方括号中的任意一个字符的一次出现

下面通过实例来解释上的意思:

1. *

Shell脚本基础—编写脚本会遇到的各种问题_第12张图片

2. [ ]

这里写图片描述

3. ?

这里写图片描述

4. [ ]?

这里写图片描述

5. 删除所有带file的文件:

Shell脚本基础—编写脚本会遇到的各种问题_第13张图片

命令代换和算术代换


1. 命令代换 :


两种方式:

    1. 用反引号``将命令括起来

       注意:内容其实也是一条命令
            ``反引号不要写成单引号

    2.$()将命令括起来

Shell先执行该条命令,再去将输出结果立刻代换到当前的命令行中

代码解释:

Shell脚本基础—编写脚本会遇到的各种问题_第14张图片

Shell脚本基础—编写脚本会遇到的各种问题_第15张图片

2. 算术运算:

常用的算术运算符: (()) 双括号

而这个只能用做+-*/% <<和()的运算符,并且只能进行整数运算

代码解释:
Shell脚本基础—编写脚本会遇到的各种问题_第16张图片

Shell脚本基础—编写脚本会遇到的各种问题_第17张图片

错误:
Shell脚本基础—编写脚本会遇到的各种问题_第18张图片

转义字符


和C语言相似,将\当做转义字符(\还可以被当成续行)

另外:如果文件名带有-(横杠)的话,用上面的转义字符 \ 是不行的

     两种方式解决:

     1. touch -- -file1
     2. touch -- ./-file.bck

单引号和双引号的区别


C语言中:

       1. 单引号 '':用来界定字符的
       2. 双引号 "":用来界定字符串的

而Shell中,两者都是用来界定字符串的界定符

两者的区别就是:

      1. 单引号 '':将单引号的字符串按照原样输出,不做任何转换
      2. 双引号 "": 会将字符串中的转义字符·反引号都会被当做命令执行

下面通过例子来解释:

#!/bin/bash

mystring="hello bit"
echo "hello world $mystring \\ \" \\ \` `date +%Y:+%m:+%d` "
echo 'hello world $mystring \\ \" \\ \` `date +%Y:+%m:+%d` '

Shell脚本基础—编写脚本会遇到的各种问题_第19张图片

你可能感兴趣的:(Linux,Shell脚本)