Shell中的变量
一、系统变量
- 常用系统变量
H O M E 、 HOME、 HOME、PWD、 S H E L L 、 SHELL、 SHELL、USER等
显示当前Shell中所有变量:set
二、自定义变量
1.基本语法
(1)定义变量:变量=值
(2)撤销变量:unset 变量
(3)声明静态变量:readonly变量,注意:不能unset
2.变量定义规则
(1)变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建议大写。
(2)等号两侧不能有空格
(3)在bash中,变量默认类型都是字符串类型,无法直接进行数值运算。
(4)变量的值如果有空格,需要使用双引号或单引号括起来。
3、特殊变量:$n
基本语法
$n (功能描述:n为数字,$0代表该脚本名称,$1-
9
代
表
第
一
到
第
九
个
参
数
,
十
以
上
的
参
数
,
十
以
上
的
参
数
需
要
用
大
括
号
包
含
,
如
9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如
9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如{10})
4、特殊变量:$#
基本语法 $# (功能描述:获取所有输入参数个数,常用于循环)。
5、特殊变量:$*、$@
基本语法
∗
(
功
能
描
述
:
这
个
变
量
代
表
命
令
行
中
所
有
的
参
数
,
* (功能描述:这个变量代表命令行中所有的参数,
∗(功能描述:这个变量代表命令行中所有的参数,*把所有的参数看成一个整体)
@
(
功
能
描
述
:
这
个
变
量
也
代
表
命
令
行
中
所
有
的
参
数
,
不
过
@ (功能描述:这个变量也代表命令行中所有的参数,不过
@(功能描述:这个变量也代表命令行中所有的参数,不过@把每个参数区分对待)
例子:
[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
6、特殊变量:$?
基本语法
$? (功能描述:最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。)
三、运算符
1.基本语法
(1)“
(
(
运
算
式
)
)
”
或
“
((运算式))”或“
((运算式))”或“[运算式]”
(2)expr + , - , *, /, % 加,减,乘,除,取余
注意:expr运算符间要有空格
2、实例
计算(2+3)X4的值
(a)expr一步完成计算
[atguigu@hadoop101 datas]$ `expr `expr 2 + 3` \* 4`
(b)采用$[运算式]方式
[atguigu@hadoop101 datas]# S=$[(2+3)*4]
[atguigu@hadoop101 datas]# echo $S
四、条件判断
1.基本语法
[ condition ](注意condition前后要有空格)
注意:条件非空即为true,[ atguigu ]返回true,[] 返回false。
2. 常用判断条件
3.
(1)两个整数之间比较
= 字符串比较
-lt 小于(less than) -le 小于等于(less equal)
-eq 等于(equal) -gt 大于(greater than)
-ge 大于等于(greater equal) -ne 不等于(Not equal)
(2)按照文件权限进行判断
-r 有读的权限(read) -w 有写的权限(write)
-x 有执行的权限(execute)
(3)按照文件类型进行判断
-f 文件存在并且是一个常规的文件(file)
-e 文件存在(existence) -d 文件存在并是一个目录(directory)
(4)多条件判断(&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一条命令执行失败后,才执行下一条命令)
[atguigu@hadoop101 ~]$ [ condition ] && echo OK || echo notok
OK
[atguigu@hadoop101 datas]$ [ condition ] && [ ] || echo notok
notok
五、流程控制(重点)
1、if 判断
1.基本语法
(1)if [ 条件判断式 ];then
程序
fi
(2)if [ 条件判断式 ]
then
程序
fi
注意事项:
(1)[ 条件判断式 ],中括号和条件判断式之间必须有空格
(2)if后要有空格
(3)if command
then
commands
else
commands
fi
(4)嵌套if:
【1】可以使用else部分的另一种形式:elif。这样就不用再书写多个if-then语句了。elif使
用另一个if-then语句延续else部分。
if command1
then
commands
elif command2
then
more commands
fi
【2】也可以在then后面再加个else
if command1
then
commands
elif command2
then
more commands
else
commands
fi
记住,在elif语句中,紧跟其后的else语句属于elif代码块。它们并不属于之前的
if-then代码块。
例子:
#!/bin/bash
# Testing nested ifs - use elif & else
#
testuser=NoSuchUser
#
if grep $testuser /etc/passwd
then
echo "The user $testuser exists on this system."
#
elif ls -d /home/$testuser
then
echo "The user $testuser does not exist on this system."
echo "However, $testuser has a directory."
#
else
echo "The user $testuser does not exist on this system."
echo "And, $testuser does not have a directory."
fi
$
【3】
可以继续将多个elif语句串起来,形成一个大的if-then-elif嵌套组合。
if command1
then
command set 1
elif command2
then
command set 2
elif command3
then
command set 3
elif command4
then
command set 4
fi
每块命令都会根据命令是否会返回退出状态码0来执行。记住,bash shell会依次执行if语句,
只有第一个返回退出状态码0的语句中的then部分会被执行。就是哪个判断成功了就执行哪个then
例子:
2、case 语句
(1)基本语法
case variable in
pattern1 | pattern2) commands1;;
pattern3) commands2;;
) default commands;;
esac
注意事项:
1)case行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束。
2)双分号“;;”表示命令序列结束,相当于java中的break。
3)最后的“)”表示默认模式,相当于java中的default。
例子:
$ cat test26.sh
#!/bin/bash
# using the case command
#
case $USER in
rich | barbara)
echo "Welcome, $USER"
echo "Please enjoy your visit";;
testing)
echo "Special testing account";;
jessica)
echo "Do not forget to log off when you're done";;
*)
echo "Sorry, you are not allowed here";;
esac
$
3、for 循环
for var in list
do
commands
done
只要你愿意,也可以将do语句和for语句放在同一行,但必须用分号将其同列表中的值分
开:for var in list; do。
例子:
#!/bin/bash
# basic for command
for test in Alabama Alaska Arizona Arkansas California Colorado
do
echo The next state is $test
done
结果
$ ./test1
The next state is Alabama
The next state is Alaska
The next state is Arizona
The next state is Arkansas
The next state is California
The next state is Colorado
$
又一个例子:
#!/bin/bash
# another example of how not to use the for command
for test in I don\'t know if "this'll" work
do
echo "word:$test"
done
结果:
$ ./test2
word:I
word:don’t
word:know
word:if
word:this’ll
word:work
$
在第一个有问题的地方添加了反斜线字符来转义don’t中的单引号。在第二个有问题的地方
将this’ll用双引号圈起来。两种方法都能正常辨别出这个值。
你可能遇到的另一个问题是有多个词的值。记住,for循环假定每个值都是用空格分割的。
如果有包含空格的数据值,你就陷入麻烦了。
从集合中循环
例子:
#!/bin/bash
# using a variable to hold the list
list="Alabama Alaska Arizona Arkansas Colorado"
list=$list" Connecticut"
for state in $list
do
echo "Have you ever visited $state?"
done
结果
$ ./test4
Have you ever visited Alabama?
Have you ever visited Alaska?
Have you ever visited Arizona?
Have you ever visited Arkansas?
Have you ever visited Colorado?
Have you ever visited Connecticut?
$
用通配符读取目录
最后,可以用for命令来自动遍历目录中的文件。进行此操作时,必须在文件名或路径名中
使用通配符。它会强制shell使用文件扩展匹配。文件扩展匹配是生成匹配指定通配符的文件名或
路径名的过程。
例子:
#!/bin/bash
for file in /home/rich/test/*
do
if [ -d "$file" ]
then
echo "$file is a directory"
elif [ -f "$file" ]
then
echo "$file is a file"
fi
done
结果
$ ./test6
/home/rich/test/dir1 is a directory
/home/rich/test/myprog.c is a file
/home/rich/test/myprog is a file
/home/rich/test/myscript is a file
/home/rich/test/newdir is a directory
/home/rich/test/newfile is a file
/home/rich/test/newfile2 is a file
/home/rich/test/testdir is a directory
/home/rich/test/testing is a file
/home/rich/test/testprog is a file
/home/rich/test/testprog.c is a file
$
另一种结构的for循环(C语言风格)
for (( variable assignment ; condition ; iteration process ))
for (( a = 1; a < 10; a++ ))
变量赋值可以有空格;
条件中的变量不以美元符开头;
迭代过程的算式未用expr命令格式。
#!/bin/bash
# testing the C-style for loop
for (( i=1; i <= 10; i++ ))
do
echo "The next number is $i"
done
C语言风格的for命令也允许为迭代使用多个变量。循环会单独处理每个变量,你可以为每
个变量定义不同的迭代过程。尽管可以使用多个变量,但你只能在for循环中定义一种条件。
#!/bin/bash
# multiple variables
for (( a=1, b=10; a <= 10; a++, b-- ))
do
echo "$a - $b"
done
输出:
$ ./test9
1 - 10
2 - 9
3 - 8
4 - 7
5 - 6
6 - 5
7 - 4
8 - 3
9 - 2
10 - 1
$
4、while 循环
while命令的格式是:
while test command
do
other commands
done
例子:
#!/bin/bash
# while command test
var1=10
while [ $var1 -gt 0 ]
do
echo $var1
var1=$[ $var1 - 1 ]
done
$ ./test10
10
9
8
7
6
5
4
3
2
1
$
5、read读取控制台输入
read(选项)(参数)
选项:
-p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒)。
参数
变量:指定读取值的变量名
#!/bin/bash
read -t 7 -p "Enter your name in 7 seconds " NAME
echo $NAME
6、自定义函数
1.基本语法
[ function ] funname[()]
{
Action;
[return int;]
}
funname
2.经验技巧
(1)必须在调用函数地方之前,先声明函数,shell脚本是逐行运行。不会像其它语言一样先编译。
(2)函数返回值,只能通过$?系统变量获得,可以显示加:return返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255)
计算两个输入参数的和
#!/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]$ ./fun.sh
Please input the number1: 2
Please input the number2: 5
7
7、Shell工具(重点)
(1)cut
1.基本用法
cut [选项参数] filename
说明:默认分隔符是制表符
2.选项参数说明
-f 列号,提取第几列
-d 分隔符,按照指定分隔符分割列
例子:
echo $PATH | cut -d : -f 3-
解释:| 以之前的结果集做操作,-f 3 是取第3列, -f 3- 是取第3列之后的所有
(2)sed 编辑器
流编辑器则会在编辑器处理数据之前基于预先提供的一组规则来编辑数据流。
grep是过滤的意思