1. Shell & bash
bash其实就是Shell的一种
2. Shell & Shell脚本
1. 两者是不同的概念;Shell是命令行解释器
2. Shell脚本(shell script),是一种为Shell编写的脚本程序
3. 在业界,所说的Shell就是Shell脚本;
我们统一认为“Shell编程”都是指的是“Shell脚本编程”
1. 第一行:#!/bin/bash
其中#!就是一个约定的标记,用于告诉系统这个脚本需要什么解释器来执行
(/bin/bash就是这个解释器的路径);#!的名称通常叫做:"Shebang"或者"Sha-bang"
2. 除了第一行的 # ,其他行都可以用 # 来注释该行,相当于C语言中的 //
3. 等式两边禁止有空格
eg: 正确写法:a=10
4. 同样的每行写完不用用 ; 来区分行号
一般情况下,在创建一个多个文件的时候,我们需要在命令行一直输入命令,然而下次如果还有同样的操作,会很麻烦,比如:
上面的rm -rf file*
的意思就是:删除所有带file
的文件
而如何去用Shell脚本去实现这个命令呢?
#!/bin/bash
touch file1
touch file2
touch file3
touch file4
touch file5
touch file6
touch file7
touch file8
方式一 :
bash ./first.sh
其中bash是一个解释器,后面后详细介绍Shell脚本的执行过程
方式二 :
chmod +x first.sh
./first.sh
这种方式就是给脚本加了一个可执行权限(X 就是表示可执行权限)
#!/bin/bash
pwd
cd ..
pwd
按照上面的思路,上面的执行结果就是:
1. 显示当前的路径
2. 返回上一层
3. 再显示当前的路径(也就是上一层的路径)
结果:
路径是对的,可是执行之后,并没有返回上一层,这是什么情况?
下面就来介绍一下内置命令的概念以及Shell脚本执行的过程:
如上的: cd ..
还有 : export echo
1. 解释非编译型
2. 弱类型
3. 执行模式:交互式/批处理式
这里的弱类式的意思就是:变量类型不太会说明,不像C语言中有:char int string...
首先,我们都知道: 一个可执行的程序,是二进制,而这里是一个文本,那是怎么运行的?
#!/bin/bash
pwd
cd ..
pwd
一: 执行:bash ./test1.sh 后的过程 :
1. 当前进程会fork(),子进程调用exec,然后将#!后面的解释器bash程序的代码替换当前进程
2. 上面解释器的代码已经替换了子进程,下来就是一一去处理文本中的命令
3. 子进程再去fork(),让孙子进程去处理第一行的命令
将第一行命令作为参数传给解释器(当前的解释器就类似于"函数")
4. 上面只是处理了一行的命令,如果还有命令行,再去fork()
二 :从上面的执行过程,我们就可以知道,为什么会出现上面的奇怪现象?
因为:
上面的 cd.. 是在 子bash 中处理的,而对 父bash 没有影响
不准 父bash 创建子进程处理这个内置命令, 父bash 自己处理
方式一:
用 . 修饰脚本
方式二:
用 source 修饰脚本
方式一:
方式二:
变量名命名的规则 :
1. 首个字符必须为字母(a-z 或者 A-Z)
2. 中间不能有空格,可以使用下划线()
3. 不能使用标点符号
4. 不能使用bash中的关键字(可以通过help命令来查看关键字)
vim test2.sh:
#!/bin/bash
myint=22
mychar=c
myfloat=3.15
mystring="hello Shell"
echo $myint
echo $mychar
echo $myfloat
echo $mystring
而如果要实现赋过值的变量和一个字符串拼接,应该在变量名外面加上{ },为了让解释器更好的识别变量边界:
由上图我们可以看出:
1. 实现两个赋过值的变量拼接:
$a$b
直接将两个变量拼接在一起
2. 实现一个赋过值的变量和字符串拼接:
给变量外边加上花括号{};用来区分边界
3. 如果不加花括号,则会将变量和紧挨着的字符串一起当做一个新的变量
这样输出的结果就为空
#!/bin/bash
readonly mystr="hello"
echo $mystr
mystr=world
echo $mystr
Shell变量是弱类型,而这里的变量类型和C语言的变量类型是不一样的
1. 本地变量
简单的来说:本地变量就好比是C语言中的局部变量
只在当前的Shell实例中有效,其他的程序无效
2. 环境变量
类似于C语言中的全局变量
在所有的程序中都有效
命令:export 环境变量
3. Shell变量
意思就是Shell脚本中的变量
有两种 :本地变量
环境变量
#!/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个字符
(后面的表示字符的个数而不是结束位置的下标)
1. * :匹配0个或多个任意字符
2. ? : 匹配一个任意字符
3. [ ] :匹配一个方括号中的任意一个字符的一次出现
下面通过实例来解释上的意思:
两种方式:
1. 用反引号``将命令括起来
注意:内容其实也是一条命令
``反引号不要写成单引号
2. 用$()将命令括起来
Shell先执行该条命令,再去将输出结果立刻代换到当前的命令行中
代码解释:
常用的算术运算符: (()) 双括号
而这个只能用做+-*/% <<和()的运算符,并且只能进行整数运算
和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` '