[TOC]
Shell简介
什么是Shell
Shell是在Linux下的命令解释型语言(command-language interpreter),它的中文翻译为“壳”主要是用于人机交互。
Shell种类
Linux Shell的种类很多,目前流行的Shell包括ash、bash、ksh、csh、zsh等,用户可以通过查看/etc/shells 文件中的内容来查看自己主机中当前有哪些种类的Shell。
1 | [djangowang@localhost ~]# cat /etc/shells |
编写第一个Shell程序
通常写程序我们都会从Hello World开始,编写第一个Shell程序我们也从他开始。关于Hello World的由来我们可以参考( http://blog.puppeter.com/read.php?25 )。以下为第一个Shell脚本程序,通过vim命令编辑hello.sh文件,其中sh为Shell脚本的扩展名文件。
1 | #! /bin/bash Bash的命令解释器 |
变量
变量在Bash中变量顾名思义通常是可变的量,它来源于数学是计算机语言中能储存计算结果或能表示值抽象概念。
变量规范
变量名的命名须遵循如下规则:
- _ 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头
- _ 中间不能有空格,可以使用下划线(__)
- 不能使用标点符号。 不能使用Bash里的关键字(可用help命令查看保留关键字)
Bash变量案例
在Bash中变量通过”$”符来表示,以下是一个Bash脚本的案例。
1 | #!/bin/bash |
这脚本最终的结果就会在屏幕上打印出This is Shell script。
变量四种赋值方式
这四种方式包括:
- 直接赋值
- read命令赋值
- 命令赋值
- 位置参数赋值
直接赋值
以下是一个Bash脚本,它将字符串“hi my name is djangowang”赋值给变量name并通过echo命令打印变量中的内容。
1 | #!/bin/bash |
read命令赋值
read是Bash中的内建命令,它从键盘获取标准输出并赋值给变量。以下是将键盘输入的内容赋值给变量name,并通过echo命令打印变量中的内容。
1 | #!/bin/bash |
命令赋值
获取系统命令的标准输出并将标准输出内容赋值给变量command,并通过echo命令打印变量中的内容。这里注意命令赋值方式共分为两种见以下案例。
1 | #!/bin/bash |
位置参数赋值
位置参数赋值是通过通过执行脚本时传递参数赋值给变量。譬如以下脚本名为test.sh内容如下,通过执行/bin/sh test.sh hello,其中hello就是位置参数他会通过$1赋值给command变量,这里注意如果位置变量有空格又需要同时传给位置变量1可以通过“”来扩起来,譬如/bin/sh test.sh hello “hello world”。这里位置变量通过空格作为变量的分割符。
1 | #!/bin/bash |
意位置变量通常为数字$1-$9,10以上要用大括号扩起来如${10},${10}以下是案例。
1 | #!/bin/bash |
以上程序有个问题,如果位置参数要是大于10或更多这样写程序成本会很高且程序易读性也不好,这时我们可以使用shift命令,它用于参数的自动左移。
1 | #!/bin/bash |
定义变量类型
在Bash中默认为字符串类型,可以通过declare关键字指定变量的类型,还可以设置变量的属性或者删除变量。 以下介绍变量定义的七种方式:
- 字符串型
- 数值型
- 数组
- 函数
- 设置环境变量
- 只读变量
- unset变量
字符串型
Bash中的默认数据类型为字符串型。
1 | #!/bin/bash |
数值型
在Bash中字符串类型只能用于字符串比较,不能进行数学运算。我们通过declare -i来定义将变量改为数值型,并进行数学运算。
1 | declare -i number # 定义一个数值型 |
我们来对比一下字符串型与数字型。
1 | #!/bin/bash |
数组
数组中可以存放多个值。Bash只支持一维数组,不支持多维数组,初始化时不需要定义数组大小,与大部分编程语言类似数组元素的下标由0开始。
1 | declare -a array |
数组案例。
1 | #!/bin/bash |
函数
declare -f 函数名 ,用于显示函数内容。
1 | #!/bin/bash |
在Shell编程实战中应用不是很多。
设置环境变量
declare -x指定的变量会成为环境变量,可供Shell以外的程序来使用。
1 | #!/bin/bash |
只读变量
declare -r var1与readonly var1作用相同。当设置只读变量后,变量内容不可以修改。
1 | declare -r var1 # 设置一个只读变量 |
案例
1 | #!/bin/bash |
unset变量
unset用于删除变量。他有两个参数-f(仅删除函数)-v(仅删除变量)默认值。
1 | #!/bin/bash |
变量类型
在Bash中的变量是有作用域的,分别为:
- 局部变量
- 环境变量
- 内部变量
局部变量
局部变量在脚本或命令中定义,仅在当前Bash实例中有效,其他Bash启动的程序不能访问局部变量。局部变量的关键字为”local”,以下为局部变量案例。
1 | #!/bin/bash |
前者输出结果为。
1 | Hello World!!! |
去掉local输出结果为。
1 | Hello World!!! |
环境变量
所有的程序包括Bash启动的程序都能访问环境变量,有些程序需要环境变量来保证其正常运行。在Bash中可以通过以下三个命令来查看环境变量,他们区别在于:
- set 用来显示本地变量
- env 用来显示环境变量
- export -p 用来显示和设置环境变量
注:变量和环境变量的区别是:变量不能被子进程继承,而环境变量会被子进程继承。
我们还可以通过以下两个文件来设置环境变量:
- /etc/profile
- $HOME/.bash_profile
譬如bash_profile文件内容,
我们可以将自己的环境变量放在PATH后。
1 | # .bash_profile |
内部变量
内部变量是Bash程序设置的特殊变量。Bash变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了Bash的正常运行,以下包含Bash的。
内部变量 | 解释 |
---|---|
$BASH_VERSION | Bash版本 |
$HOSTNAME | hostname |
$HOME | 宿主目录(家目录) |
$PATH | 环境变量 |
$RANDOM | 随机整数 |
Bash符号相关
在Bash中存在一些特殊符号,他们主要用于标准输出时的一些格式展现,如以下:
特殊符号对照表,表1。
符号 | 含义 |
---|---|
\n | 新行 |
\r | 回车 |
\t | 制表符 |
\v | 垂直的制表符 |
\b | 后退符 |
\a | 警告(蜂鸣或是闪动) |
在Bash中这些特殊符号主要用于以下两个命令的场景:
场景1:echo命令是我们学习Bash编程中一个很常用的命令,他用于打印信息到标准输出,譬如。
1 | [root@blog.puppeter.com_centos ~]# echo "hello world" # 打印hello world到标准输出 |
目前echo有两个参数:
- -n 不解析参数内的特殊符号
- -e 默认值,解析参数内的特殊符号
1 | [root@blog.puppeter.com_centos ~]# echo -n "hello\tworld" # 不解析参数内制表符,同时不执行echo后的\n,特殊符号见表1 |
场景2:我们再来看一下Printf命令。与echo相同的都是打印内容到屏幕上,但printf命令模仿 C 程序库(library里的 printf() 程序,它由 POSIX 标准所定义,因此使用printf的脚本比使用echo移植性好,以下为案例。
1 | #!/bin/bash |
我们再来看一下Printf命令。与echo相同的都是打印内容到屏幕上,但printf命令模仿 C 程序库(library里的 printf() 程序,它由 POSIX 标准所定义,因此使用printf的脚本比使用echo移植性好,以下为案例。
1 | #!/bin/bash |
Read命令
read是Bash的内建命令,主要用于从键盘读取内容赋值给变量,它有以下常用参数:
- -p :指定多个变量
1
2
3
4
5#!/bin/bash
read -p “please input your name " name
echo "your name is $name"
exit 0 - -n :计数输入的字符
1
2
3#!/bin/bash
read -n6 -p “please input your password(lengh must be over 6 numbers)" passwd
exit 0 - -s :隐藏输入,不回显内容到终端
1
2
3#!/bin/bash
read -s -n6 -p “please input your password(lengh must be over 6 numbers)" passwd
exit 0 - -t :超时等待时间
1
2
3
4
5
6
7
8#!/bin/bash
read -t 5 -p “please input your name" name
if [ $? -eq 0 ];then
echo "your name is $name"
else
echo "timeout"
fi
exit 0
条件语句
- if..then..fi
- if..then..else..fi
- if..then..elif..fi
if..then..fi
首先来看一下if..then..fi的语法,它有多种书写方式 。
方式1
1 | #!/bin/bash |
方式2
1 | if [ 条件语句 ] |
方式3
1 | if (());then |
方式4
1 | if command ;then |
注:初学者一定要注意以上if..then语法中,条件语句两边都是有空格的,缺少一个空格都会报错且不容易被注意到。
再来看一下关于if..then..fi的案例。
1.if..then的[]案例,比较两个值是否相等,此方式主要用于字符串匹配。
1 | #!/bin/sh |
2.if..then的(())案例,数学方式比较大小,此方式主要用于数学方式的比较。
1 | #!/bin/bash |
3.if..command,判断是否为目录,此方式主要用于调用命令来判断命令返回最终结果。
1 | #!/bin/bash |
if..then..else..fi
if..then..else..fi的语法。
方式1
1 | #!/bin/bash |
方式2
1 | if [ 条件语句 ] |
再来看一下if..then..else..fi的案例。
1 | #!/bin/sh |
if..then..elif..fi
if..then..elif..fi的语法:
方式1
1 | if [ 条件语句 ];then |
方式2
1 | if [ 条件语句 ] |
if..then..elif..fi的案例。
案例1
1 | #!/bin/bash |
文件比较符。
[ ]括号 | (())扩容 | 含义 |
---|---|---|
-eq | == | 等于 |
-ne | != | 不等于 |
-gt | > | 大于 |
-ge | >= | 大于等于 |
-lt | < | 小于 |
-le | <= | 小于等于 |
案例2
通过条件语句实现的计算器。
1 | #!/bin/bash |
循环语句
Shell支持五中循环方式:
- while循环
- for循环
- for..in循环
- until循环
- select循环
while循环
首先来看一下while循环的语法。
方式1
1 | while [ 条件表达式 ];do # 推荐 |
方式2
1 | while [ 条件表达式 ] |
方式3
1 | while [ 条件表达式 ];do 执行内容 ;done # Bash语句大都可以写作一行,只不过可读性差 |
方式4
1 | while command;do |
再来看一下while循环的案例。
1.打印1-100的数字。
1 | #!/bin/bash |
2.打印1-100间的偶数。
1 | #!/bin/bash |
3.打印/etc/passwd信息。
1 | #!/bin/bash |
4.死循环
死循环中条件表达式永远为真,如果要退出死循环可以用ctrl+c方式。
1 | #!/bin/bash |
for循环
for循环的语法。
方式1
1 | for (( ; ; ));do # 推荐 |
方式2
1 | for (( ; ;)) |
方式3
1 | for ((;;));do 执行内容 ;done |
for循环的案例。
1.打印1-100的数字。
1 | for ((i=1; i<=100; i ++)); do |
2.打印1-100间的奇数。
1 | #!/bin/bash |
3.死循环。死循环中条件表达式永远为真,如果要退出死循环可以用ctrl+c方式.
1 | #!/bin/bash |
for..in 循环
for..in循环的语法。
方式一
1 | for 变量 in 条件语句;do # 推荐 |
方式二
1 | for 变量 in 条件语句 |
方式三
1 | for 变量 in 条件语句;do 执行语句 ;done |
案例
1.打印1-5的数字。
1 | for loop in 1 2 3 4 5 ;do |
2.打印1-100间的数字。
1 | for loop in `seq 1 100`;do |
3.创建1-100的文件夹。
1 | for loop in `seq 1 100`;do |
until循环
until 循环执行一系列命令直至条件为 true 时停止。until 循环与 while 循环在处理方式上刚好相反,一般while循环优于until循环,但在某些时候,也只是极少数情况下,until 循环更加有用。首先来看一下until循环的语法。
方式一
1 | until command;do # 推荐 |
方式二
1 | until command |
select循环
select 是个无限循环,因此要记住用break命令退出循环或用exit命令终止脚本,也可以按ctrl+c 退出循环。我们首先看select的语法。
方式一
1 | select name [in list ];do # 推荐 |
方式二
1 | select name [in list ] |
案例,通常我们使用select用来做列表,案例如下。
1 | #!/bin/bash |
分支语句
Shell的分支语句其实就是case,我们先来看一下它的语法。
1 | case 匹配内容 in |
案例1,计算器。
1 | #!/bin/bash |
案例2,位置参数。
1 | #!/bin/bash |