三、Shell变量
3.1 系统变量
$HOME、$PWD、$SHELL、$USER等
查看系统变量的值
[root@localhost ~]$ echo $HOME
/root
[root@localhost ~]$
3.2 自定义变量
3.2.1 基本语法
- 定义变量:变量=值
- 撤销变量:unset 变量
- 声明静态变量:readonly变量,注意:不能unset
3.2.2 自定义变量规则
- 变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建议大写。
- 等号两侧不能有空格
- 在bash中,变量默认类型都是字符串类型,无法直接进行数值运算。
- 变量的值如果有空格,需要使用双引号或单引号括起来。
- 使用双引号,可以识别空格之外的其他变量,使用单引号则会只会忽略空格!
- 使用反引号,可以将语句运行的结果作为值赋值给变量!
3.2.3 自定义变量例子
- 定义变量A
[root@localhost ~]$ A=5
[root@localhost ~]$ echo $A
5
- 给变量A重新赋值
[root@localhost ~]$ A=8
[root@localhost ~]$ echo $A
8
- 撤销变量A
[root@localhost ~]$ unset A
[root@localhost ~]$ echo $A
[root@localhost ~]$
- 声明静态的变量B=2,不能unset
[root@localhost ~]$ readonly B=2
[root@localhost ~]$ echo $B
2
[root@localhost ~]$ B=9
-bash: B: readonly variable
- 在bash中,变量默认类型都是字符串类型,无法直接进行数值运算
[atguigu@hadoop102 ~]$ C=1+2
[atguigu@hadoop102 ~]$ echo $C
1+2
- 变量的值如果有空格,需要使用双引号或单引号括起来,无需注意数据的类型
[atguigu@hadoop102 ~]$ D=I love banzhang
-bash: world: command not found
[atguigu@hadoop102 ~]$ D="I love banzhang"
[atguigu@hadoop102 ~]$ echo $A
I love banzhang
- 使用双引号可以识别变量
[root@0725pc shells]$ echo $A
hello
[root@0725pc shells]$ B="hello $A"
[root@0725pc shells]$ echo $B
hello hello
[root@0725pc shells]$ C='hello $A'
[root@0725pc shells]$ echo $C
hello $A
- 使用反引号,将命令运行的结果赋值给参数,即A=
ll
等同于 A=$(ll)
[root@0725pc shells]$ D=`ll`
[root@0725pc shells]$ echo $D
总用量 4 -rwxr--r--. 1 root root 23 10月 8 21:36 test1.sh
[root@0725pc shells]$ E=$(ll)
[root@0725pc shells]$ echo $E
总用量 4 -rwxr--r--. 1 root root 23 10月 8 21:36 test1.sh
- 可把变量提升为全局环境变量,可供其他Shell程序使用
export 变量名
[root@localhost ~]$ vim helloworld.sh
在helloworld.sh文件中增加echo $B
#!/bin/bash
echo "helloworld"
echo $B
[root@localhost ~]$ ./helloworld.sh
Helloworld
发现并没有打印输出变量B的值。
[root@localhost ~]$ export B
[root@localhost ~]$ ./helloworld.sh
helloworld
每次修改 /etc/profile时,我们会执行source /etc/profile,source的作用就是执行文件中所有的export命令!
3.3 特殊变量
3.3.1 $n
- 基本语法
$n(功能描述:n为数字,$0代表该脚本名称,$1- 9 代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如 9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如 9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如{10}) - 案例实操:输出该脚本文件名称、输入参数1和输入参数2 的值
[atguigu@hadoop101 datas]$ touch parameter.sh
[atguigu@hadoop101 datas]$ vim parameter.sh
#!/bin/bash
echo "$0 $1 $2"
[atguigu@hadoop101 datas]$ chmod 777 parameter.sh
[atguigu@hadoop101 datas]$ ./parameter.sh cls xz
./parameter.sh cls xz
3.3.2 $#
- 基本语法
$# (功能描述:获取所有输入参数个数,常用于循环)。 - 案例实操:获取输入参数的个数
[atguigu@hadoop101 datas]$ vim parameter.sh
#!/bin/bash
echo "$0 $1 $2"
echo $#
[atguigu@hadoop101 datas]$ chmod 777 parameter.sh
[atguigu@hadoop101 datas]$ ./parameter.sh cls xz
parameter.sh cls xz
2
3.3.3 ∗ 、 *、 ∗、@
- 基本语法
∗ (功能描述:这个变量代表命令行中所有的参数, * (功能描述:这个变量代表命令行中所有的参数, ∗(功能描述:这个变量代表命令行中所有的参数,*把所有的参数看成一个整体)
@ (功能描述:这个变量也代表命令行中所有的参数,不过 @ (功能描述:这个变量也代表命令行中所有的参数,不过 @(功能描述:这个变量也代表命令行中所有的参数,不过@把每个参数区分对待) - 案例实操:打印输入的所有参数
[atguigu@hadoop101 datas]$ vim parameter.sh
#!/bin/bash
echo "$0 $1 $2"
echo $#
echo $*
echo $@
[atguigu@hadoop101 datas]$ bash parameter.sh 1 2 3
parameter.sh 1 2
3
1 2 3
1 2 3
3.3.4 $?
- 基本语法
$? (功能描述:最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。) - 案例实操:判断helloworld.sh脚本是否正确执行
[atguigu@hadoop101 datas]$ ./helloworld.sh
hello world
[atguigu@hadoop101 datas]$ echo $?
0
四、Shell运算符
4.1 基本语法
- “$((运算式))” 或 “$[运算式]”
- expr + , - , *, /, % 加,减,乘,除,取余
注意:
expr运算符间要有空格;
*号需要转义为*,否则会被视为通配符;
运算指的都是整数的运算,浮点运算需要借助其他的命令!
4.2 运算符案例
- 计算3+2的值
[atguigu@hadoop101 datas]$ expr 2 + 3
5
- 计算3-2的值
[atguigu@hadoop101 datas]$ expr 3 - 2
1
- 计算(2+3)×4的值
(a)expr一步完成计算
[atguigu@hadoop101 datas]$ expr `expr 2 + 3` \* 4
20
(b)采用$[运算式]方式
[atguigu@hadoop101 datas]$ S=$[(2+3)*4]
[atguigu@hadoop101 datas]$ echo $S
五、Shell条件判断
5.1 基本语法
[ condition ](注意condition前后要有空格)
注意:条件非空即为true,[ atguigu ]返回true,[] 返回false。
5.2 常用判断条件
- 两个整数之间比较
符号 | 作用 |
---|---|
= | 字符串比较(等号两侧要加空格) |
-lt | 小于(less than) |
-le | 小于等于(less equal) |
-eq | 等于(equal) |
-gt | 大于(greater than) |
-ge | 大于等于(greater equal) |
-ne | 不等于(Not equal) |
- 按照文件权限进行判断
符号 | 作用 |
---|---|
-r | 有读的权限(read) |
-w | 有写的权限(write) |
-x | 有执行的权限(execute) |
- 按照文件类型进行判断
符号 | 作用 |
---|---|
-f | 文件存在并且是一个常规的文件(file) |
-e | 文件存在(existence) |
-d | 文件存在并是一个目录(directory) |
-s | 文件存在且不为空 |
-L | 文件存在且是一个链接(link) |
5.3 常用判断条件案例实操
- 23是否大于等于22
[atguigu@hadoop101 datas]$ [ 23 -ge 22 ]
[atguigu@hadoop101 datas]$ echo $?
0
- helloworld.sh是否具有写权限
[atguigu@hadoop101 datas]$ [ -w helloworld.sh ]
[atguigu@hadoop101 datas]$ echo $?
0
- /home/atguigu/cls.txt目录中的文件是否存在
[atguigu@hadoop101 datas]$ [ -e /home/atguigu/cls.txt ]
[atguigu@hadoop101 datas]$ echo $?
1
- 多条件判断(&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一条命令执行失败后,才执行下一条命令)
[atguigu@hadoop101 ~]$ [ condition ] && echo OK || echo notok
OK
[atguigu@hadoop101 datas]$ [ condition ] && [ ] || echo notok
notok
六、Shell流程控制
6.1 if 判断
- 基本语法
if [ 条件判断式 ]
then
程序
elif 条件判断式
then 程序..
else 程序..
fi
或
if [ 条件判断式 ] ; then
程序..
elif [条件判断式] ; then
程序..
else 程序
fi
注意事项:
(1)[ 条件判断式 ],中括号和条件判断式之间必须有空格
(2)if后要有空格
- 案例实操:如果输入的数字是1,2,3则输出你输入的数字是xx,否则输出,你输入的数字不是1,2,3
[root@0725pc shells]$ cat test3.sh
#! /bin/bash
if [ $1 -eq 1 ]
then
echo "你输入的是1啊!"
elif [ $1 -eq 2 ]
then
echo "你输入的是2啊!"
elif [ $1 -eq 3 ]
then
echo "你输入的是3啊!"
else echo "你输入的不是1,2,3啊!"
fi
[root@0725pc shells]$ bash test3.sh 3
你输入的是3啊!
[root@0725pc shells]$ bash test3.sh 2
你输入的是2啊!
[root@0725pc shells]$ bash test3.sh 1
你输入的是1啊!
[root@0725pc shells]$ bash test3.sh 4
你输入的不是1,2,3啊!
6.2 case 语句
- 基本语法
case $变量名 in
"值1")
如果变量的值等于值1,则执行程序1
;;
"值2")
如果变量的值等于值2,则执行程序2
;;
…省略其他分支…
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac
注意事项:
1) case行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束。
2) 双分号“;;”表示命令序列结束,相当于java中的break。
3) 最后的“*)”表示默认模式,相当于java中的default。
- 案例实操:输入一个数字,如果是1,则输出banzhang,如果是2,则输出cls,如果是其它,输出renyao。
[atguigu@hadoop101 datas]$ touch case.sh
[atguigu@hadoop101 datas]$ vim case.sh
!/bin/bash
case $1 in
"1")
echo "banzhang"
;;
"2")
echo "cls"
;;
*)
echo "renyao"
;;
esac
[atguigu@hadoop101 datas]$ chmod 777 case.sh
[atguigu@hadoop101 datas]$ ./case.sh 1
1
6.3 for 循环
6.3.1 基本语法1
for (( 初始值;循环控制条件;变量变化 ))
do
程序
done
或
for (( 初始值;循环控制条件;变量变化 )); do 程序; done
案例实操:从1加到100
[atguigu@hadoop101 datas]$ touch for1.sh
[atguigu@hadoop101 datas]$ vim for1.sh
#!/bin/bash
s=0
for((i=0;i<=100;i++))
do
s=$[$s+$i]
done
echo $s
[atguigu@hadoop101 datas]$ chmod 777 for1.sh
[atguigu@hadoop101 datas]$ ./for1.sh
“5050”
[root@0725pc shells]$ tail -n 4 test1.sh
SUM2=0
for((i=0;i<=10;i++));do SUM2=$(($SUM2+$i)); done
echo "从1加到100的值是:$SUM2"
[root@0725pc shells]$ ./test1.sh
从1加到100的值是:55
6.3.2 基本语法2
for 变量 in 值1 值2 值3…
do
程序
done
或
for 变量 in 1 2 3; do 程序; done
或
for 变量 in {1..3}; do 程序; done
案例实操:打印所有输入参数
[atguigu@hadoop101 datas]$ touch for2.sh
[atguigu@hadoop101 datas]$ vim for2.sh
#!/bin/bash
#打印数字
for i in $*
do
echo "ban zhang love $i "
done
[atguigu@hadoop101 datas]$ chmod 777 for2.sh
[atguigu@hadoop101 datas]$ bash for2.sh cls xz bd
ban zhang love cls
ban zhang love xz
ban zhang love bd
多种写法
[root@0725pc shells]$ cat test2.sh
#! /bin/bash
for i in 1 2 3
do
echo $i
done
echo "--------------------"
for i in 1 2 3 ;do echo $i;done
echo "--------------------"
for i in {1..3};do echo $i;done
[root@0725pc shells]$ ./test2.sh
1
2
3
--------------------
1
2
3
--------------------
1
2
3
比较 ∗ 和 *和 ∗和@区别
- ∗ 和 *和 ∗和@都表示传递给函数或脚本的所有参数,不被双引号“”包含时,都以$1 2 … 2 … 2…n的形式输出所有参数。
[atguigu@hadoop101 datas]$ touch for.sh
[atguigu@hadoop101 datas]$ vim for.sh
#!/bin/bash
for i in $*
do
echo "ban zhang love $i "
done
for j in $@
do
echo "ban zhang love $j"
done
[atguigu@hadoop101 datas]$ bash for.sh cls xz bd
ban zhang love cls
ban zhang love xz
ban zhang love bd
ban zhang love cls
ban zhang love xz
ban zhang love bd
- 当它们被双引号“”包含时,“$*”会将所有的参数作为一个整体,以“$1 2 … 2 … 2…n”的形式输出所有参数;“$@”会将各个参数分开,以“$1” “ 2 ” … ” 2”…” 2”…”n”的形式输出所有参数。
[atguigu@hadoop101 datas]$ vim for.sh
#!/bin/bash
for i in "$*"
#$*中的所有参数看成是一个整体,所以这个for循环只会循环一次
do
echo "ban zhang love $i"
done
for j in "$@"
#$@中的每个参数都看成是独立的,所以“$@”中有几个参数,就会循环几次
do
echo "ban zhang love $j"
done
[atguigu@hadoop101 datas]$ chmod 777 for.sh
[atguigu@hadoop101 datas]$ bash for.sh cls xz bd
ban zhang love cls xz bd
ban zhang love cls
ban zhang love xz
ban zhang love bd
6.4 while 循环
6.4.1 基本语法
while [ 条件判断式 ]
do
程序
done
或
while((表达式))
do
程序
done
6.4.2 案例实操
- 从1加到100
[atguigu@hadoop101 datas]$ touch while.sh
[atguigu@hadoop101 datas]$ vim while.sh
#!/bin/bash
s=0
i=1
while [ $i -le 100 ]
do
s=$[$s+$i]
i=$[$i+1]
done
echo $s
[atguigu@hadoop101 datas]$ chmod 777 while.sh
[atguigu@hadoop101 datas]$ ./while.sh
5050
- 从0开始,累加加11次
[root@0725pc shells]$ bash test3.sh
11
[root@0725pc shells]$ cat test3.sh
#! /bin/bash
NUM=0
while((NUM<=10));do let NUM++; done
echo $NUM
七、函数
8.1 系统函数
8.1.1 basename
-
基本语法
basename [string / pathname] [suffix]
选项:suffix为后缀,如果suffix被指定了,basename会将pathname或string中的suffix去掉。 -
功能描述:basename命令会删掉所有的前缀包括最后一个(‘/’)字符,然后将字符串显示出来。
-
案例实操:截取该/home/atguigu/banzhang.txt路径的文件名称
[atguigu@hadoop101 datas]$ basename /home/atguigu/banzhang.txt
banzhang.txt
[atguigu@hadoop101 datas]$ basename /home/atguigu/banzhang.txt .txt
banzhang
8.1.2 dirname
-
基本语法
dirname 文件绝对路径
-
功能描述:从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分)
-
案例实操:获取banzhang.txt文件的路径
[atguigu@hadoop101 ~]$ dirname /home/atguigu/banzhang.txt
/home/atguigu
8.2 自定义函数
- 基本语法
function funname[()]
{
Action;
[return int;]
}
funname
-
经验技巧
- 必须在调用函数地方之前,先声明函数,shell脚本是逐行运行。不会像其它语言一样先编译。
- 函数返回值,只能通过$?系统变量获得,可以显示加:return返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255)
-
案例实操:计算两个输入参数的和
[atguigu@hadoop101 datas]$ touch fun.sh
[atguigu@hadoop101 datas]$ vim fun.sh
#!/bin/bash
function sum()
{
s=0
s=$[ $1 + $2 ]
echo "$s"
}
read -p "Please input the number1: " n1;
read -p "Please input the number2: " n2;
sum $n1 $n2;
[atguigu@hadoop101 datas]$ chmod 777 fun.sh
[atguigu@hadoop101 datas]$ ./fun.sh
Please input the number1: 2
Please input the number2: 5
7