目录
介绍
格式要求
示例
变量
环境变量
使用
查看所有环境变量
常见环境变量
自定义变量
命名规则
使用
只读变量
删除变量
变量作用域
1.局部变量
2.全局变量
3.环境变量
字符串
单双引号
字符串拼接
获取长度
字符串提取
基本运算符
算数运算符
编辑
关系运算符
逻辑运算符
布尔运算符
字符串运算符
文件测试运算符
流程控制
if
单分支结构
双分支结构
多分枝结构
for
while
case
函数
不带参数没有返回值的函数
有返回值的函数
带参数的函数
输入/输出重定向
输入重定向符号
输出重定向符号
输出附加定向符
即时文件定向符
与文件描述字有关的重定向
学习 Shell 是为了提高我们自己工作效率,提高产出,让我们在更少的时间完成更多的事情。Shell 几乎是 IT 企业必须使用的运维自动化编程语言,特别是在运维工作中的服务监控、业务快速部署、服务启动停止、数据备份及处理、日志分析等环节里,shell 是不可缺的。
Shell 编程就是对一堆 Linux 命令的逻辑化处理
1.脚本以#!/bin/bash开头
2.脚本需要有可执行权限
1.新建文件
touch test.sh
2.添加执行权限
chmod +x test.sh //
使脚本具有执行权限
3.修改文件
使用vim命令修改test.sh文件(vim test.sh),添加内容
#!/bin/bash
#第一个shell小程序,echo 是linux中的输出命令。
echo "hello word!
shell 的第一行比较特殊,一般都会以#!开始来指定使用的 shell 类型
4.编译
运行脚本:./test.sh
shell 编程中一般分为三种变量:
PATH
, HOME
等..., 这类变量我们可以直接使用),使用 env
命令可以查看所有的环境变量,而 set 命令既可以查看环境变量也可以查看自定义变量。 echo $HOME
env
PATH 决定了 shell 将到哪些目录中寻找命令或程序
HOME 当前用户主目录
HISTSIZE 历史记录数
LOGNAME 当前用户的登录名
HOSTNAME 指主机的名称
SHELL 当前用户 Shell 类型
LANGUAGE 语言相关的环境变量,多语言可以修改此环境变量
MAIL 当前用户的邮件存放目录
PS1 基本提示符,对于 root 用户是#,对于普通用户是$
1.命名只能使用英文字母,数字和下划线,首个字符不能以数字开头,但是可以使用下划线(_)开头。
2.中间不能有空格,可以使用下划线(_)。
3.不能使用标点符号。
4.不能使用 bash 里的关键字(可用 help 命令查看保留关键字)
#!/bin/bash
#自定义变量hello
hello="hello world"
echo $hello
echo "helloworld!"
使用一个定义过的变量,只要在变量名前面加$符号即可
使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变
unset 命令可以删除变量,变量被删除后不能再次使用。unset 命令不能删除只读变量。
局部变量在脚本或者命令中定义,仅在当前shell进程中有效
在命令行中定义变量name,创建脚本test.sh并访问变量name,则访问不到
name='test' #在命令行中定义变量name
vim test.sh
echo $name
~
~bash test.sh #命令行执行test.sh
发现脚本里访问不到变量name,应为定义的name是局部变量只在当前终端进程中有效
在当前shell中任何地方可以使用的变量,且在子shell中也有效。通过命令env可以查看当前shell中的所有全局变量。定义一个全局变量可以使用export命令
export name=test # 定义全局变量name
vim test.sh
echo $name
~
~bash test.sh #命令行执行test.sh
#输出
test
export定义的全局变量是临时的,当关闭执行定义的shell进程后,定义的变量就会被销毁
所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量
环境变量本质上就是全局变量,只不过它是在启动终端时通过执行初始化脚本预定义的。
启动终端后直接输入env命令显示得所有变量都是环境变量。要定义环境变量可以在一下文件中通过export定义:
~/.bashrc 只对当前用户的终端有效
~/.profile 只对当前用户的终端有效
/etc/bash.bashrc对所有用户的终端有效
字符串可以用单引号,也可以用双引号,也可以不用引号
#!/bin/bash
a = 'A'
b = "B"
echo $a
echo $b
输出:
A
B
特点:
单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
单引号字串中不能出现单独一个的单引号,但可成对出现,作为字符串拼接使用。
双引号里可以有变量 - 双引号里可以出现转义字符
#!/bin/bash
a = 'A'
b = "B"
c = "$a$b"
echo $c
输出:
AB
在上面的基础之上加上echo ${#c}即可:
#!/bin/bash
a = 'abcd'
b = "efgh"
c = "$a$b"
echo $c
echo ${#c}
输出:
abcdefgh
8
字符串的提取,主要是采用切片的方法来获取
#!/bin/bash
a = 'abcd'
b = "efgh"
c = "$a$b"
echo $c
echo ${#c}
echo ${a:1:3}
输出:
abcdefgh
8
bcd
Shell 编程支持下面5种运算符:
1.算数运算符
2.关系运算符
3.布尔运算符
4.字符串运算符
5.文件测试运算符
#!/bin/bash
a=6;b=3;
val=`expr $a + $b`
val1=`expr $a - $b`
val2=`expr $a \* $b`
val3=`expr $a / $b`
val4=`expr $a % $b`
echo $val
echo $val1
echo $val2
echo $val3
echo $val4
关系运算符只支持数字,不支持字符串,除非字符串的值是数字
#!/bin/bash
score=90;
maxscore=100;
if [ $score -eq $maxscore ]
then
echo "A"
else
echo "B"
fi输出结果:
B
#!/bin/bash
a=$(( 1 && 0))
echo $a;输出结果:
0
逻辑与运算只有相与的两边都是1,与的结果才是1;否则与的结果是0
#!/bin/bash
a="abc";
b="efg";
if [ $a = $b ]
then
echo "a 等于 b"
else
echo "a 不等于 b"
fi输出:
a 不等于 b
比如我们定义好了一个文件路径file="/usr/learnshell/test.sh"
如果我们想判断这个文件是否可读,可以这样if [ -r $file ]
如果想判断这个文件是否可写,可以这样-w $file
在任何一门编程语言中都离不开流程控制语句,使用流程控制语句可以帮助程序处理各类复杂的操作,常用的流程控制语句,比如: if-else,while,for循环等,在linux 的shell 编程语法中,也提供了丰富的流程控制语句
if分为单分支结构、双分支结构和多分枝结构。
语法结构:
if 条件
then 命令
fi
#!/bin/bash
a="abc";
b="efg";
if [ $a = $b ]
then
echo "a 等于 b"
fi
行一次条件匹配,如果与条件匹配,则执行相应的预设命令,反之去执行不匹配的预设命令
语法结构:
if 条件
then
命令
else
命令
fi
#!/bin/bash
a="abc";
b="efg";
if [ $a = $b ]
then
echo "a 等于 b"
else
echo "a 不等于 b"
fi输出:
a 不等于 b
进行多次条件判断,一次在匹配中匹配成功都会执行相应的预设命令
语法结构:
if 条件1
then
命令1
elif 条件2
then
命令2
elif 条件3
then 命令3
.......
else
命令N
fi
for循环语句允许脚本一次性读取多个文件信息,然后逐一对信息进行操作,每次赋值后即执行一次循环体; 直到列表中的元素耗尽,循环结束
语法组成:由for...in 、do 、done组成
for 变量名 in {取值列表} 取值列表:{n..N} 表示一个范围,或者提前定义一个文件,注入 内容
do
命令序列
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
通常情况下 shell 变量调用需要加 $,但是 for 的 (()) 中不需要,下面来看一个例子:
#!/bin/bash
for((i=1;i<=5;i++));do
echo $i;
done;
双小括号方法,即((…))格式,也可以用于算术运算
whil和for 都为条件循环语句,二者的区别在于while的条件循环是不知道最终执行多少次(可定义结束时间)
而for是有使用范围和目标的。
循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“true”,则执行一次循环;直到条件测试状态为“false”终止循环
语法组成:由while true 、do 、done组成 或while : 、do 、done及while 条件判断 、do、done
where 条件判断
do
命令序列
done
#!/bin/bash
int=1
while(( $int<=5 ))
do
echo $int
let "int++"
done
case 语句可以使脚本程序的结构更加清晰、层次分明,常用于服务的启动、重启、停止的脚本,有的服务不提供这种控制脚本,需要用case语句编写
语法格式:
case 变量值 in
模式 1)
命令序列 1
;;
模式 2)
命令序列 1
;;
* )
默认命令序列
esac
#!/bin/bash
NUM=4
case $NUM in
1)
echo NUM == 1
;;
2)
echo NUM == 2
;;
3)
echo NUM == 3
;;
4)
echo NUM == 4
;;
*)
echo xxxxx
;;
esac输出:
NUM == 4
case支持glob风格的通配符:*
: 任意长度任意字符?
: 任意单个字符[]
:指定范围内的任意单个字符a|b
: a或b
Shell 函数的本质是一段可以重复使用的脚本代码,这段代码被提前编写好了,放在了指定的位置,使用时直接调取即可
格式
function name() {
statements
[return value]
}
function :关键字,用来定义函数
name:函数名
statements:函数要执行的代码
[return value]:函数的返回值,返回值可写可不写
由{}包裹的部分称为函数体,调用一个函数,实际上就是执行函数体中的代码
#!/bin/bash
hello(){
echo "这是我的第一个 shell 函数!"
}
echo "-----函数开始执行-----"
hello
echo "-----函数执行完毕-----"输出结果:
-----函数开始执行-----
这是我的第一个 shell 函数!
-----函数执行完毕-----
#!/bin/bash
funWithReturn(){
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum 和 $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturnecho "输入的两个数字之和为 $?"
输出结果:
输入第一个数字:
1
输入第二个数字:
2
两个数字分别为 1 和 2 !
输入的两个数字之和为 3
#!/bin/bash
funWithParam(){
echo "第一个参数为 $1 !"
echo "第二个参数为 $2 !"
echo "第十个参数为 $10 !"
echo "第十个参数为 ${10} !"
echo "第十一个参数为 ${11} !"
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73输出结果:
第一个参数为 1 !
第二个参数为 2 !
第十个参数为 10 !
第十个参数为 34 !
第十一个参数为 73 !
参数总数有 11 个!
作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !
$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数
另外,还有几个特殊字符用来处理参数:
执行一个命令时,通常会打开3个文件,标准输入文件(stdin)、标准输出文件(stdout)、标准出错输出文件(stderr),分别对应的是键盘、屏幕、屏幕终端。
输入重定向符<
的作用是,把命令(或可执行文件)的标准输入重定向到制定文件,例如,在一个文件cmds
中包含以下内容:
cat cmds
echo "your working diretory is `pwd`"
echo "your name is `logname`"
echo "The time is `date`"
who
然后输入:
bash < cmds
shell命令解释程序从cmds中读取命令行并执行 输入重定向的一般形式是:
命令<文件名
输出重定向符>
的作用是,把命令(或可执行程序)的标准输出重新定向到指定文件中,例如:shell脚本exp1的内容如下:
echo "The time is `date`"
echo "Your name is `logname`"
echo "Working diretory is `pwd`"
echo "It has `ls -l|wc -l` files."
执行下列命令:
exp1 > tmp1
输出重定向的一般形式是:
命令>文件名
输出附加定向符>>
的作用是,把命令(或可执行程序)的输出附加到指定文件的后面,而该文件原有内容不被破坏,例如:
ps -l >> psfile
把ps
命令的输出附加到文件psfile
的结尾处。利用cat
命令就可看到psfile
的全部信息,包括原有内容和新添内容。
使用输出附加定向符时,如果指定文件不存在,就创建一个新文件,输出附加定向符的一般形式是:
命令 >> 文件名
即时文件有重新定向符<<
、一对标记符以及若干输入行组成,它允许把shell程序的输入行重新定向到一个命令,即时文件的形式是:
命令 [参数]«标记符 输入行 标记符
每一个打开的文件都有系统赋予的一个文件描述字,它是一个小整数。一个文件打开后,用户可以直接用这个描述子来引用对应的文件。如前所述,系统为每个进程自动打开三个标准文件(即校准输入、标准输出和错误输出),其文件描述字分别是0,1,2。 前面已经列举了标准输入和标准输出重新定向的例子。标准错误也可重定向倒一个文件中,其一般形式是:
命令 2>文件名 命令 2>>文件名