1.shell简介
终端中输入一系列命令完成一些操作,但是我们一条一条输入命令,这样就会很麻烦,shell脚本可以将很多条命令放到一个文件里面,然后直接运行。
shell 脚本类似 windows 的批处理文件,shell 脚本就是将连续执行的命令写成一个文件。
shell 脚本提供数组、循环、条件判断等功能。shell 脚本一般是 Linux 运维、测试、系统管理员需要掌握的。
2. 开头
程序必须以下面的行开始(必须方在文件的第一行):
#!/bin/sh
符号#!用来告诉系统它后面的参数是用来执行该文件的程序。在这个例子中我们使用/bin/sh来执行程序。
当编写脚本完成时,如果要执行该脚本,还必须使其可执行,给它提升权限:
chmod 777 filename
这样才能用./filename 来运行
3. 注释
在进行shell编程时,以#开头的句子表示注释,直到这一行的结束。
4. 变量
变量是任何一种编程语言都必不可少的组成部分,变量用来存放各种数据。脚本语言在定义变量时通常不需要指明类型,直接赋值就可以,Shell 变量也遵循这个规则。
在 Bash shell 中,每一个变量的值都是字符串,无论你给变量赋值时有没有使用引号,值都会以字符串的形式存储。
4.1 定义变量
shell 支持以下三种定义变量的方式:
variable=value
variable=‘value’
variable=“value”
variable 是变量名,value 是赋给变量的值。如果 value 不包含任何空白符(例如空格、Tab 缩进等),那么可以不使用引号;如果 value 包含了空白符,那么就必须使用引号包围起来。使用单引号和使用双引号也是有区别的。
注意,赋值号=的两边不能有空格。
Shell 变量的命名规范和大部分编程语言都一样:
变量名由数字、字母、下划线组成;
必须以字母或者下划线开头;
不能使用 Shell 里的关键字(通过 help 命令可以查看保留关键字)。
4.2 使用变量
使用一个定义过的变量,只要在变量名前面加美元符号$即可,如:
author="严长生
echo $author
echo ${author}
变量名外面的花括号{ }是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:
skill=“Java”
echo “I am good at ${skill}Script”
如果不给 skill 变量加花括号,写成echo “I am good at $skillScript”,解释器就会把 $skillScript 当成一个变量(其值为空),代码执行结果就不是我们期望的样子了。
推荐给所有变量加上花括号{ },这是个良好的编程习惯。
4.3修改变量的值
已定义的变量,可以被重新赋值,如:
url=“http://c.biancheng.net”
echo ${url}
url=“http://c.biancheng.net/shell/”
echo u r l 第 二 次 对 变 量 赋 值 时 不 能 在 变 量 名 前 加 {url} 第二次对变量赋值时不能在变量名前加 url第二次对变量赋值时不能在变量名前加,只有在使用变量时才能加$
4.4 删除变量
使用 unset 命令可以删除变量。语法:
unset variable_name
变量被删除后不能再次使用;unset 命令不能删除只读变量。
举个例子:
#!/bin/sh
myUrl=“http://c.biancheng.net/shell/”
unse myUrl
echo $myUrl
上面的脚本没有任何输出。
4.5环境变量
全局变量只在当前 Shell 进程中有效,对其它 Shell 进程和子进程都无效。如果使用export命令将全局变量导出,那么它就在所有的子进程中也有效了,这称为“环境变量”。
环境变量被创建时所处的 Shell 进程称为父进程,如果在父进程中再创建一个新的进程来执行 Shell 命令,那么这个新的进程被称作 Shell 子进程。当 Shell 子进程产生时,它会继承父进程的环境变量为自己所用,所以说环境变量可从父进程传给子进程。不难理解,环境变量还可以传递给孙进程。
注意,两个没有父子关系的 Shell 进程是不能传递环境变量的,并且环境变量只能向下传递而不能向上传递,即“传子不传父”。
环境变量也是临时的
通过 export 导出的环境变量只对当前 Shell 进程以及所有的子进程有效,如果最顶层的父进程被关闭了,那么环境变量也就随之消失了,其它的进程也就无法使用了,所以说环境变量也是临时的。
5.参数
5.1位置参数
我们先来说一下 Shell 位置参数是怎么回事。
运行 Shell 脚本文件时我们可以给它传递一些参数,这些参数在脚本文件内部可以使用$n的形式来接收,例如,$1 表示第一个参数,$2 表示第二个参数,依次类推。
同样,在调用函数时也可以传递参数。Shell 函数参数的传递和其它编程语言不同,没有所谓的形参和实参,在定义函数时也不用指明参数的名字和数目。换句话说,定义 Shell 函数时不能带参数,但是在调用函数时却可以传递参数,这些传递进来的参数,在函数内部就也使用$n的形式接收,例如,$1 表示第一个参数, 2 表 示 第 二 个 参 数 , 依 次 类 推 。 这 种 通 过 2 表示第二个参数,依次类推。 这种通过 2表示第二个参数,依次类推。这种通过n的形式来接收的参数,在 Shell 中称为位置参数。
在讲解变量的命名时,我们提到:变量的名字必须以字母或者下划线开头,不能以数字开头;但是位置参数却偏偏是数字,这和变量的命名规则是相悖的,所以我们将它们视为“特殊变量”。
5.1.1给脚本传递位置参数
请编写下面的代码,并命名为 test.sh:
#!/bin/bash
echo “Language: $1”
echo "URL: 2 " 运 行 t e s t . s h , 并 附 带 参 数 : [ m o z h i y a n @ l o c a l h o s t ] 2" 运行 test.sh,并附带参数: [mozhiyan@localhost ~] 2"运行test.sh,并附带参数:[mozhiyan@localhost ] cd demo
[mozhiyan@localhost demo]$ . ./test.sh Shell http://c.biancheng.net/shell/
Language: Shell
URL: http://c.biancheng.net/shell/
其中Shell是第一个位置参数,http://c.biancheng.net/shell/是第二个位置参数,两者之间以空格分隔。
5.1.2 给函数传递位置参数
请编写下面的代码,并命名为 test.sh:
#!/bin/bash
#定义函数
function func(){
echo "Language: $1"
echo "URL: $2"
}
#调用函数
func C++ http://c.biancheng.net/cplus/
运行 test.sh:
[mozhiyan@localhost ~]$ cd demo
[mozhiyan@localhost demo]$ . ./test.sh
Language: C++
URL: http://c.biancheng.net/cplus/
注意事项
如果参数个数太多,达到或者超过了 10 个,那么就得用${n}的形式来接收了,例如 10 、 {10}、 10、{23}。{ }的作用是为了帮助解释器识别参数的边界,这跟使用变量时加{ }是一样的效果。
5.1.3特殊变量
上节我们讲到了 n , 它 是 特 殊 变 量 的 一 种 , 用 来 接 收 位 置 参 数 。 本 节 我 们 继 续 讲 解 剩 下 的 几 个 特 殊 变 量 , 它 们 分 别 是 : n,它是特殊变量的一种,用来接收位置参数。本节我们继续讲解剩下的几个特殊变量,它们分别是: n,它是特殊变量的一种,用来接收位置参数。本节我们继续讲解剩下的几个特殊变量,它们分别是:#、 ∗ 、 *、 ∗、@、 ? 、 ?、 ?、$。
$0:当前脚本的文件名。
$n(n≥1):传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是 $1,第二个参数是 $2。
$#:传递给脚本或函数的参数个数。
$*:传递给脚本或函数的所有参数。
$@:传递给脚本或函数的所有参数
$?:上个命令的退出状态,或函数的返回值,
$$:当前 Shell 进程 ID。对于 Shell 脚本,就是这些脚本所在的进程 ID。
6 其他命令
dirs: 这个命令显示栈里面所有的路径,一定会包含当前路径,常用参数如下
dirs -v 显示栈里面的所有路径和下标,通过下标,我们可以用pushd +下标到这个目录,然后popd+下标把这个路径在栈里面弹出来,
dirs -c 清除栈里所有路径,但是当前路径不会删除
set -e : 在"set -e"以后出现的代码,一旦出现了返回值非零,整个脚本就会当即退出。有的人喜欢使用这个参数,是出于保证代码安全性的考虑
set -o errexit 等价与set -e 比较好理解,遇到指令运行后返回非0 就返回终止
source FileName :在当前bash环境下读取并执行FileName中的命令。
注:该命令通常用命令“.”来替代。
如:source .bash_rc 与 . .bash_rc 是等效的。
make
一般上, make 是 make all 的简写,它根据 makefile 的规则,将 C/C++ 档案编译成 .o 档案,然后进一步产生可执行档。
make clean :清楚上次的make命令所产生的object文件(后缀为”.o“的文件)及可执行文件
pushd:我们可以添加目录到栈(dirs)里面,比如添加当前目录pushd . 然后如果需要到栈里面具体哪个路径的话我们可以pushd +下标,如果是-下标的话,我们是从栈底算起
popd:我们可以弹出栈的最上面的一个路径,我们也可以popd +n弹出栈里面指定的具体路径,如果是-下标的话,我们是从栈底算起
dirname $0 在命令行状态下单纯执行 $ cd
dirname $0是毫无意义的。因为他返回当前路径的"."。 这个命令写在脚本文件里才有作用,他返回这个脚本文件放置的目录,并可以根据这个目录来定位所要运行程序的相对位置(绝对位置除外)。 在/home/admin/test/下新建test.sh内容如下: cd
dirname $0echo
pwd然后返回到/home/admin/执行 sh 在命令行状态下单纯执行 $ cd
dirname $0` 是毫无意义的。因为他返回当前路径的"."。
这个命令写在脚本文件里才有作用,他返回这个脚本文件放置的目录,并可以根据这个目录来定位所要运行程序的相对位置(绝对位置除外)