Shell 基础语法介绍
Shell 介绍
1. 定义变量的时候,"=" 两侧不能有空格
2. if 时的方括号内,"=" 或 "==" 两侧必须要有空格,且表达式和方括号也要保持空格
3. $(Linux命令) 或者 `Linux 命令` 用来执行 Linux 命令,并得到命令执行后的结果
4. if 的判断条件要写在 [] 中
5. ((表达式)) 用作 if 语句的判断条件时,不加 $ ,用在其它地方需要加 $
6. 算数运算可以使用 `expr $a + $b`
什么是 Shell
它类似于 DOS 下的 command
和后来的 cmd.exe
,Shell 既是一种命令语言,又是一种程序设计语言
Shell 是一个用 C 语言编写的程序,通过 Shell 用户可以访问操作系统内核服务
什么是 Shell Script
Shell 编程跟 java、php 编程一样,是一个编程语言,需要一个能编写代码的文本编辑器和一个能解释执行的脚本解释器
1. Shell Script 是一种为 shell 编写的脚本程序
2. Shell 编程一般指 shell 脚本编程,不是指开发 shell 自身
shell 脚本的规范
#!
是一个标记,除了第一行的 #
,其它行的 #
表示注释
1. 编辑脚本的时候,需要在 shell 脚本中第一行的进行标记
2. 该标记用来告诉系统这个脚本需要什么解释器来执行
#!/bin/bash
Shell 解释器
查看 Shell
解释器
Shell 解释器可以解析我们编写的脚本,注意:大多数 Linux 系统默认的 Shell 是 Bash
# 查看系统中的 Shell 解释器
cat /etc/shells
常见 Shell 解释器
注意:Linux
上,sh
已经被 bash
代替,/bin/sh
往往是指向 /bin/bash
的符号链接
① sh(Bourne shell)
1. 由 AT&T 公司的 Steve Bourne 开发,为了纪念他,就用他的名字命名了
2. sh 是 UNIX 上的标准 shell,很多 UNIX 版本都配有 sh
3. sh 是第一个流行的 Shell
② Bash
1. Bash 是 sh 的升级版本,是著名的开源软件项目
2. 目前大多数的 Linux 版本都使用 Bash 作为默认的 Shell 程序
3. 当运行 Shell 程序时,实际运行的是 Bash 程序
③ Csh
1. 使用了 C 语言的语法风格,在用户的命令行交互界面上进行了很多改进,并增加了历史,别名,文件名替换,作业掏等功能
2. Csh 适用于用户命令交互操作
Shell 脚本的执行方式
Shell 有 3 种执行方式
① sh 执行
进入脚本的工作目录,然后使用对应的 sh
或 bash
来执行脚本,这种执行方式,脚本文件不需要具有可执行权限
# 执行 start.sh
sh start.sh
② 工作目录执行
执行脚本时,先进入到脚本所在的目录,然后使用 ./
脚本方式执行,这种执行方式,必须保证脚本文件具有可执行权限
# 在当前目录执行脚本
./start.sh
③ 绝对路径执行
绝对路径中执行,这种执行方式,必须保证脚本文件具有可执行权限
# 执行脚本
/opt/server/start.sh
数据类型
① 字符串
字符串是 shell 编程中最常用最有用的数据类型,字符串可以用单引号,也可以用双引号,也可以不用引号
建议使用双引号,因为双引号里可以有变量和特殊字符,可以按照变量和特殊字符去使用
② 整数型
在 Shell 中所有的变量默认都是字符串型。默认情况下,所有的数值都是不能进行运算的
Shell 变量
变量介绍
Shell 变量是一种很 弱
的变量,默认情况下,一个变量保存一个字符串
若要进行数学运算,必须使用一些命令,例如:let、declare、expr、双括号等
变量的种类
① 用户变量(使用较多)
② 环境变量(程序运行时设置)
③ 特殊变量(对参数判断和命令返回值判断时会使用)
变量的定义规则
变量名=变量值
① 变量名可以由字母、数字和下画线组成,但是不能以数字开头
② 在 Bash 中,变量的默认类型都是字符串型,如果要进行数值运算,则必须使用特殊命令
③ 变量用等号 =
连接值,=
左右两侧不能有空格
④ 变量值中如果有空格,则需要使用单引号或双引号包含,双引号括起 来的内容 $
和 反引号
者都拥有特殊含义,而单引号括起来的内容都是普通字符
# 示例
name="kyle white"
⑤ 在变量值中,可以使用转义符
⑥ 不能使用 bash
里的关键字
用户变量
定义变量
对变量赋于字符串值时,建议使用引号将其包裹。如果字符串中存在空格,一定要使用单引号或双引号将整个内容包裹
注意::单引号里的内容原封不动的输出,双引号里有变量的调用则会调用变量
name=kyle
访问变量
# 第一种方式
"$变量"
# 第二种方式
${变量}
定义脚本
#!/bin/bash
name="kyle"
age=23
echo "name=${name},age=${age}"
变量交互式赋值
1. 可以使用 read 关键字从键盘获取内容赋值给变量
2. 可以通过 $(linux命令) 或者 linux 命令来执行 linux 命令,并将命令的执行结果赋值给变量
#!/bin/bash
echo "welcome!"
echo "please enter your name?"
read name
hostname_string=$(hostname)
date_string=`date`
echo "hello, $name"
echo "$date_string $hostname_string"
定义只读变量
使用 readonly
定义变量
#!/bin/bash
echo "welcome!"
echo "please enter your name?"
read name
readonly name
name=root
echo "$name"
删除变量
使用 unset
命令可以删除变量
#!/bin/bash
name=root
unset name
echo "$name"
环境变量
环境变量说明
当 shell 程序启动时,都自动设置一组变量,这组变量就是环境变量
shell 中的所有命令都可以使用这些变量,环境变量可以在 /etc/profile
中设置,环境变量的名字习惯上使用大写字母
查看环境变量
# 查看所有的环境变量
env
# 查看 JAVA_HOME 的环境变量
echo $JAVA_HOME
设置环境变量
# 编辑环境变量配置文件
vim /etc/profile
# 增加环境变量
export KYLE_HOME=blog.csdn.net
# 刷新环境变量
source /etc/profile
特殊变量
特殊变量说明
在执行 Shell 脚本时,向脚本传递参数,这时候可以使用特殊变量来获取参数
Shell 常用的特殊变量如下
变量 | 解释 |
---|---|
$# | 命令行参数的个数 |
$n | $1 表示第一个参数,$2 表示第二个参数,以此类推 |
$0 | 当前程序的名称 |
$? | 前一个命令或许或函数的返回码 |
$* | 以 参数1 参数2 ... 形式保存所有参数 |
$@ | 以 “参数1”“参数2” 形式保存所有参数 |
$$ | 本程序的(进程ID号)PID |
$! | 上一个命令的PID |
获取执行参数
#!/bin/bash
echo "Shell Param Test"
echo "shll_name:$0"
echo "param2:$1"
echo "param3:$2"
echo "param4:$3"
echo "parm_count:$#"
echo "$*"
$*
与 $@
的区别
# 相同点
都是引用所有参数
# 不同点
只有在双引号中体现出来,假设在脚本运行时写了三个参数 1、2、3
"*" 等价于 "1 2 3"(传递了 1 个参数)
"@" 等价于 "1" "2" "3"(传递了 3 个参数)
字符串
字符串中的单引号
单引号里的任何字符都会原样输出
单引号字符串中的变量是无效的,单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用
#!/bin/bash
name="kyle"
echo 'my name is $name'
字符串中的双引号
1. 双引号里可以有变量
2. 双引号里可以出现转义字符
字符串拼接
① 双引号拼接
#!/bin/bash
name="kyle"
age=23
str1="name=$name"
str2="age=$age"
echo $str1 $str2
② 单引号拼接
#!/bin/bash
name="kyle"
age=23
str1='name=$name'
str2='age=$age'
echo $str1 $str2
③ 转译原样输出
#!/bin/bash
name="kyle"
age=23
str1="name=$name"
str2="age=$age"
str3="hello,\$$name\$ "
echo $str1 $str2 $str3
获取字符串长度
#!/bin/bash
name="kyle"
echo "${#name}"
截取字符串
从第 2 个字符开始,截取 2 个字符
#!/bin/bash
str="Hello Shell"
echo "${str:2:2}"
查找字符串
查找字符串 pa
,返回第一次出现的索引
#!/bin/bash
str="spark is spark"
echo `expr index "$str" pa`
算数运算符
运算说明
Shell 支持包括:算术、关系、布尔、字符串等运算符,简单的数学运算可以通过 expr
实现
注意: expr
是一款表达式计算工具,使用它能完成表达式的求值操作
1. 表达式和运算符之间要有空格,例如 1+1 是不对的,必须写成 1 + 1
2. 条件表达式要放在方括号之间,并且要有空格,例如: [a==b] 是错误的,必须写成 [ a == b ]
① 通过 $((运算表达式))
计算
# 有没有空格都可以
a=5
b=10
echo $((a+b))
② 通过 expr
表达式计算
# 必须要有空格
a=5
b=10
echo `expr $a + $b`
③ 通过 $[运算表达式]
计算
# 有没有空格都可以
a=5
b=10
echo $[a+b]
常用运算符
运算符 | 说明 | 举例 |
---|---|---|
+ | 加法 | expr $a + $b 结果为 30。 |
- | 减法 | expr $a - $b 结果为 -10。 |
* | 乘法 | expr $a \* $b 结果为 200。 |
/ | 除法 | expr $b / $a 结果为 2。 |
% | 取余 | expr $b % $a 结果为 0。 |
= | 赋值 | a=$b 将把变量 b 的值赋给 a。 |
== | 相等。用于比较两个数字,相同则返回 true。 | [ a == b ] 返回 false。 |
!= | 不相等。用于比较两个数字,不相同则返回 true。 | [ a != b ] 返回 true。 |
运算示例
#!/bin/bash
a=5
b=10
# 加法运算
each `expr $a + $b`
# 减法运算
echo `expr $a - $b`
# 乘法运算,注意*号前面需要反斜杠
echo `expr $a \* $b`
# 除法运算
echo $a / $b
# 还可以通过$(())、$[]进行算术运算
echo "a = $a"
echo $((a+b))
echo $[a+b]
流程控制
if 语句
常用的关系运算符
① 数字判断
运算符 | 说明 |
---|---|
-eq | 检测两个数是否相等,相等返回 true |
-ne | 检测两个数是否不相等,不相等返回 true |
-gt | 检测左边的数是否大于右边的,如果是,则返回 true |
-lt | 检测左边的数是否小于右边的,如果是,则返回 true |
-ge | 检测左边的数是否大于等于右边的,如果是,则返回 true |
-le | 检测左边的数是否小于等于右边的,如果是,则返回 true |
② 字符串判断
判断符 | 说明 |
---|---|
-n STRING | 字符串长度不为零 |
-z STRING | 字符串长度为0 |
= | 判断两个字符串是否一样 |
!= | 判断两个字符串是否不一样 |
③ 文件判断
判断符 | 说明 |
---|---|
-f | 存在且是普通文件 |
-d | 存在且是目录 |
-h | 存在且是符号链接 |
-e | 文件存在 |
–r | 文件存在并且可读 |
–w | 文件存在并且可写 |
–x | 文件存在并且可执行 |
判断条件使用
① 使用关系运算符
# 方括号和运算表达式之间必须要有空格
if [ $a -eq $b ]
② 使用算数运算符
# 运算符两侧有没有空格都行
# 第一种
if (($a == $b))
# 第二种
if ((a == b))
if 语法
注意:中括号需要和表达式左右留一个空格,示例:if [ a -gt b ]
,否则会报错
# 语法格式
if condition
then
command1
command2
...
commandN
fi
示例一:判断系统当前是否有多个 ssh
进程
#!/bin/bash
if [ $(ps -ef | grep -c "ssh") -gt 1 ]
then
echo true
fi
示例二:判断指定目录是否存在,不存在则创建目录
#!/bin/bash
dir="/opt/log"
if [ ! -d $dir ]
then
mkdir -p $dir
fi
if else语法
if condition
then
command1
command2
...
commandN
else
command
fi
示例一:判断是否为管理员登入
#!/bin/bash
echo "please enter your name"
username read
if [ "root"=$username ]
then
echo "welcome,Manager"
else
echo "welcome,Tourist"
fi
示例二:if else
结合 test
命令使用
说明:test 命令可以做各种测试并在测试成功或失败时返回它的退出状态码(为0表示为真,为1表示为假)
#!/bin/bash
num1=$((2*4))
num2=$((1+2))
# test $num1 -eq $num2
if test $[num1] -eq $[num2]
then
echo "num1 = num2"
else
echo "num1 != num2"
fi
if else-if else
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
案例一:计算学生的成绩范围
#!/bin/bash
read -p "please enter your score: " score
if [ $score -ge 90 ] && [ $score -le 100 ]; then
echo "your grade is A"
elif [ $score -ge 60 ] && [ $score -lt 90 ]; then
echo "your grade is B"
elif [ $score -ge 0 ] && [ $score -lt 60 ]; then
echo "your grade is C"
else
echo "your inpur is wrong"
fi
案例二:使用 (())
符号
#!/bin/bash
read -p "please enter your score: " score
if (($score >= 90)) && (($score <= 100)); then
echo "your grade is A"
elif (($score >= 60)) && (($score < 90)); then
echo "your grade is B"
elif (($score > 0)) && (($score < 60)); then
echo "your grade is C"
else
echo "your input is wrong"
fi
for 循环
字符型循环
1. 当变量值在列表里,for循环即执行一次所有命令,使用变量名获取列表中的当前取值
2. 命令可为任何有效的 shell 命令和语句
3. in 列表可以包含替换、字符串和文件名
4. in 列表是可选的,如果不用它,for 循环使用命令行的位置参数
# 格式
for 变量 in 值1 值2 值3…
do
程序
done
案例一:打印 in
列表
#!/bin/bash
for value in aa bb cc dd
do
echo "value is: $value"
done
案例二:打印字符串
#!/bin/bash
for str in "I am who I am"
do
echo $str
done
案例三:遍历命令执行结果
#!/bin/bash
for file in $(ls -a /opt)
do
echo $file
done
数字型循环
for ((初始值;循环控制条件;变量变化))
do
程序
done
案例一:1-100
的累加值
#!/bin/bash
sum=0
for ((i=0; i<=100; i= i+1))
do
# sum=(($sum+$i))
sum=$((sum+i))
done
echo "sum is : $sum"
while 循环
while 条件
do
程序
done
案例一:1-100
的累加值
#!/bin/bash
sum=0
i=0
while ((i<=100))
do
sum=$((sum+i))
i=$((i+1))
done
echo "sum is : $sum"
案例二:使用 let
简洁代码
注意:let
可以实现变量前不加 $
的计算,同时可以实现计算表达式的简写
#!/bin/bash
sum=0
i=0
while ((i<=100))
do
let sum+=i
let i++
done
echo "sum is : $sum"
死循环
① 第一种写法
while :
do
command
done
② 第二种写法
while true
do
command
done
③ 第三种写法
for (( ; ; ))
case 语句
shell case 语句为多选择语句,可以用 case
语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令
注意:case
语句也可以使用循环控制语句
# 使用注意
1. 取值后面必须为单词 in,每一模式必须以右括号结束
2. 取值可以为变量或常数
3. 匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;
4. 如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令
case 值 in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac
案例一:根据输入的值返回今天是星期几
#!/bin/bash
read -p"请输入 1 - 7 之间的数字 : " input
case $input in
1) echo "Today is Monday"
;;
2) echo "Today is Tuesday"
;;
3) echo "Today is Wednesday"
;;
4) echo "Today is Thursday"
;;
5) echo "Today is Friday"
;;
6) echo "Today is Saturday"
;;
7) echo "Today is Sunday"
;;
*) echo "Wrong input,check your input"
;;
esac
循环控制
① continue
跳出本次循环,然后继续执行下次循环
案例:只输出 1-10
内的偶数,遇到奇数则使用 continue
跳过本次循环
#!/bin/bash
for((i=1;i<=10;i=i+1))
do
if [ `expr $i % 2 ` != 0 ]; then
continue
fi
echo "当前的数为: $i"
done
② break
中断循环
案例:当遇到 5
的时候,中断当前的循环,后面的循环不会执行
#!/bin/bash
for((i=1;i<=10;i=i+1))
do
if [ $i == 5 ]; then
break
fi
echo "当前的数为: $i"
done
select 语句
select 表达式是 bash 的一种扩展应用,擅长于交互式场合,用户可以从一组不同的值中进行选择
注意:select 是个无限循环,因此要记住用 break
命令退出循环,或用 exit
命令终止脚本
select var in ... ;
do
commond
done
.... now $var can be used ...
案例一:选择最喜欢的城市
#!/bin/bash
echo "which is your favorite city ? "
PS3="please enter your choice:"
select var in "Beijing" "Shanghai" "Shenzhen" "Hangzhou"
do
break;
done
echo "You have selected $var"
函数
定义函数
用户可以自定义函数,然后在 shell
脚本中可以随便调用,定义格式如下:
注意:函数的返回值必须是整数,如果是字符串会报错
# 1. 可以带 function fun() 定义,也可以直接 fun() 定义,不带任何参数
# 2. 参数返回,可以显示加 return 返回;如果不加,将以最后一条命令运行结果,作为返回值
# 3. 所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至 shell 解释器首次发现它时,才可以使用。调用函数仅使用其函数名即可
[ function ] funname()
{
action;
[return int;]
}
案例一:定义一个没有返回值的函数,打印欢迎语句
#!/bin/bash
print()
{
echo "Welcome to Shell World,${USER}"
}
print
案例二:获取函数的执行结果
说明:函数返回值在调用该函数后通过 $?
来获得
#!/bin/bash
sum()
{
read -p "请输入第一个数: " a
read -p "请输入第二个数: " b
return $(( a + b ))
}
echo "两个数的和为 $? "
案例三:定义一个方法,获取指定文件夹的大小
#!/bin/bash
# 定义函数
getDirSize()
{
array=($(du -sh /opt/server))
size=${array[0]}
}
# 调用函数
getDirSize
echo "文件夹的大小为:$size"
函数参数
在 Shell 中,调用函数时可以向其传递参数,在函数体内部,可以获取参数的值
注意:不能使用 $
获取 10
及以后的参数,需要使用 ${}
来获取
#!/bin/bash
parmFunc(){
echo "参数 1 : $1"
echo "参数 2 : $2"
echo "参数 10 : $10"
echo "参数 10 : ${10}"
echo "参数 11 : ${11}"
echo "参数数量: $#"
echo "字符串输出参数: $*"
}
parmFunc 1 2 3 4 5 6 7 8 9 11 12
数组
数组说明
Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小
注意:不能使用 $
获取 10
及以后的参数,需要使用 ${}
来获取
1. 数组元素的下标由 0 开始
2. 元素用"空格"符号分割开
3. 数组中可以存放多个值
# 格式
array_name=(value1 ... valuen)
# 示例
my_array=("a" 1 2 "jack")
获取数组元素
# 格式
${array_name[index]}
#!/bin/bash
my_array=("a" 1 2 "jack")
echo "元素 1 : ${my_array[0]}"
echo "元素 2 : ${my_array[1]}"
echo "元素 3 : ${my_array[2]}"
echo "元素 4 : ${my_array[3]}"
获取数组所有元素
#!/bin/bash
my_array=("a" 1 2 "jack")
echo "数组所有元素 : ${my_array[*]}"
echo "数组所有元素 : ${my_array[@]}"
获取数组长度
#!/bin/bash
my_array=("a" 1 2 "jack")
echo "数组所有元素 : ${#my_array[*]}"
echo "数组所有元素 : ${#my_array[@]}"
遍历数组
① 第一种遍历方式
#!/bin/bash
my_array=("a" 1 2 "jack")
for ele in ${my_array[*]}
do
echo $ele
done
② 第二种遍历方式
#!/bin/bash
my_array=("a" 1 2 "jack")
for((i=0;i<=${#my_array[@]};i=i+1))
do
echo ${my_array[$i]}
done