shell的基本语法总结
上周日的时候,宇哥让我们搭起来HADOOP集群,他有一个要求:用脚本实现自动安装。什么是脚本?什么是集群?虽然什么都不懂,但可以学啊。花了一天的时间了解了HADOOP的安装流程和SSH免密的原理和方法,又花了一天学习了一下shell的基本语法。接下来花了两三天的时间成功写出了三个脚本。脚本不算完美,有冗余也有瑕疵,但至少能成功运行,有足够多的注解和选项。下次接触ssh估计要很久以后了,所以这里把这几天的收获总结一下,以备后用。
shell基本常识
shell
shell 是一个交互性命令解释器。shell独立于操作系统,这种设计让用户可以灵活选择适合自己的shell。shell让你在命令行键入命令,经过shell解释后传送给操作系统(内核)执行。
根据我的理解,LINUX系统下的shell相当于WINDOWS系统下的CMD,我们可以通过在shell中输入命令行来执行命令。比如我们想重启计算机,我们可以选择在GUI下点击电源,然后点击重启,再点确认,比较麻烦。而在shell下,我们只要输入”sudo shutdown -r now”就能重启了。shell给了我们一个框架,允许我们输入命令行来操作计算机。基本所有GUI能做的事情,利用shell的命令行都能做,而且更快。
更强的是,我们甚至可以利用shell编程,写出脚本,让shell代替我们输入一系列的命令。
脚本
脚本语言又被称为扩建的语言,或者动态语言,是一种编程语言,用来控制软件应用程序,脚本通常以文本(如ASCII)保存,只在被调用时进行解释或编译。
根据我的理解,脚本就是代替人的手动输入,自动输入一系列的命令行执行操作的程序。用户可以使用脚本来把一些常用的操作组合成一组序列,方便运维,或是方便实现某些功能。
shell脚本
- shell是一个命令解释器,shell脚本语言是一种非类型解释型语言。
- shell脚本一般以”.sh”作为后缀名,这是一个标准。因为LINUX文件类型并不以后缀名区分,所以你也可以用其它的后缀名。
- “Bash”脚本是shell脚本中最常用的类型,大部分LINUX使用的命令解释器都是”Bash”。
- shell脚本开头以”#/bin/bash”来定义该脚本为shell脚本的bash脚本。之后所有以”#”开头的都是注释。
执行脚本
执行脚本有多种方法
命令 | 备注 |
---|---|
chmod o+x test_shell.sh ./test_shell.sh | 这种方法是改变刚写好的脚本文件权限使其可执行,然后用默认方式执行这个可执行文件 |
/bin/bash test_shell.sh | 用命令解释器来解释这个脚本,建议用这种方法。(前边的”/bin/”可以省略) |
变量
shell是一种非类型解释型语言,所以其中的变量都不需要实现声明,在调用时使用”$”符号。
它的变量分为
局部变量 |
环境变量 |
举个例子:
#/bin/bash
numb=15 #直接赋值局部变量
echo "$numb" #直接调用局部变量
echo "$UID" #直接调用环境变量
自己在脚本中定义的是局部变量,系统中有的是系统变量,也就是环境变量。常见的环境变量包括
符号 | 作用 |
---|---|
$0 | 当前程序名 |
$n | 当前程序的第n个参数 |
$* | 当前程序的所有参数(参数即命令行参数) |
$# | 当前程序参数的个数 |
$UID | 当前用户名 |
$PWD | 当前所在目录 |
$? | 判断上一条命令是否执行正确(正确时该参数值为0) |
IF判断
格式
if (表达式);then
语句1
else
语句2
fi
举个例子:
#!/bin/bash
echo -e "\033[32mhello world\033[30m"
if [ $? -eq 0 ];then
echo -e "\033[31morder carried out successfully!\033[32m"
else
echo -e "\033[31morder carried out badly!\033[32m"
fi
shell中的括号和其他语言有所不同,它的括号很有讲究。内容太多这里不一一列举,可以去网络上自己搜集:
http://www.360doc.com/content/16/1019/11/13644263_599562112.shtml
运算符
逻辑运算符
符号 | 作用 | |
---|---|---|
-f | 判定文件是否存在 | |
-d | 判定目录是否存在 |
整数比较
符号 | 作用 | |
---|---|---|
-eq | 相等 | |
-ne | 不相等 | |
-lt | 小于 | |
-gt | 大于 | |
-le | 小等于 | |
-ge | 大等于 |
逻辑表达
符号 | 作用 |
---|---|
-a | 与 |
-o | 或 |
-z | 是否为空串 |
! | 反义 |
反引号
单引号和双引号都会将其中内容以字符串的形式进行解析,而反引号恰恰相反,它会将其中内容以命令的形式解析。
举个例子:
`date + %Y%m%d`
上边这条命令的运行结果是当前日期。
多重判断格式
if (表达式);then
语句1
elif (表达式);then
语句2
else
语句3
fi
case和select 语句
case语句格式
case $i in "a" "b" "c"
a )
语句1
;;
b )
语句2
;;
c )
语句3
;;
* )
语句4
;;
esac
“in”后边的参数不是必须写的,case语句在做多选项判断的时候比if语句好用一些
select语句格式
PS3=表述
select var in "a" "b" "c";
do
语句...
break;
done
- select一般用于选择语句的创建,它会将每个参数以列表的形式列出来并给每个选择项一个标号,通过输入标号来执行相应的语句。
- select语句本身是自带循环的,如果不加break那么这个语句会一直执行下去。
- “PS3”是配合select使用的环境变量,个人更喜欢使用echo打印信息,而不是使用PS3。
case和select联用
实际编码中case和select常常联起来用,select负责输入,case负责对select的输入进行分别处理。
举个简单的例子:
#!/bin/bash
PS3="Select your favorite color:"
select var in "red" "green" "yellow";
do
case $var in
"red" )
echo -e "\033[31myour favorite color is red!\033[0m"
;;
"green" )
echo -e "\033[32myour favorite color is green!\033[0m"
;;
"yellow" )
echo -e "\033[33myour favorite color is yellow!\033[0m"
;;
* )
echo -e "\033[31myour input is illegal!\033[0m"
;;
esac
break;
done
循环语句
for循环
for循环和c语言中for循环的作用是一样的,只是格式不一样,直接举个例子:
#!/bin/bash
for (( i=0; i<100; i++ ))
do
echo -e "current value of i is $i"
done
while
和for循环一样,没什么好说的。举个例子。
#!/bin/bash
i="no"
while [[ $i != "yes" ]]
do
echo -e "current value of i is $i"
read i
done
数组
数组赋值
shell中的数组同样有好几种定义方法,可以采用:
array_name=(valuea, valueb, valuec ...)
的方法一次给数组赋多个值。
也可以采用:
array_name[0]=valuea
array_name[1]=valueb
...
的方法分别赋值。
值得注意的是数组的下标可以不连续。
读取数组
符号 | 作用 | |
---|---|---|
{array_name[index]} | 读取下标为index的数组中的某个元素的值 | |
${array_name[* / @]} | 使用*或@获取数组中所有元素 | |
${#array_name[*]} | 获取数组长度 |
函数
函数的定义方法很简单
function_name() {#定义函数
语句 ...
}
function_name #调用函数
需要注意的是:
1. shell中函数不存在向前声明,在使用函数前必须先定义。在使用函数前必须先定义好。
2. 函数存在局部变量。shell内的变量相对于系统而言是局部变量,而函数内的变量相对于shell又是局部变量。
3. 调用函数是直接用调用LINUX命令的方式调用即可。