- 接之前的博客Linux相关用法,学习Shell的前提就是要回Linux基本常用命令:
Linux常用命令知识点大全(1)文件目录类和用户权限类命令
Linux常用命令知识点大全(2)文件权限类、磁盘进程管理类、解压缩命令
文章目录
一、Shell语言简述
Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。Ken Thompson 的 sh 是第一种 Unix Shell,Windows Explorer 是一个典型的图形界面 Shell。下图分别为windows和linux的shell界面,可以在里面使用命令对系统进行操作,我之前总结的Linux命令都是在第二幅shell页面进行的。
-
Linux提供的Shell解释器有:
- sh:Bourne shell,sh 是 UNIX 上的标准 shell,sh 是第一个流行的 Shell。
- csh:C shell,这个 shell 的语法有点类似C语言,所以才得名为 C shell ,简称为 csh。
- tcsh:tcsh 是 csh 的增强版,加入了命令补全功能,提供了更加强大的语法支持。
- bash:bash shell 是 Linux 的默认 shell。
-
在现代的 Linux 上,sh 已经被 bash 代替,/bin/sh往往是指向/bin/bash的软链接。
-
CentOS默认的解释器为bash
-
脚本格式:以 # ! / b i n / b a s h \#!/bin/bash #!/bin/bash开头,指定解释器为bash。
-
需求:创建一个shell脚本,输出hello world
-
创建文件,写入内容hello world
[hadoop1@hadoop1 test]$ touch hello.sh # 创建脚本文件
[hadoop1@hadoop1 test]$ vim hello.sh # 输入 #!/bin/bash (换行) echo "hello world" 保存退出
- 第一种执行方法:bash + 脚本文件相对路径或绝对路径
[hadoop1@hadoop1 test]$ bash hello.sh # 执行脚本,输出内容 hello world
- 第二种执行方法:直接利用脚本文件相对路径或绝对路径(需拥有可执行权限x)
[root@hadoop1 test]$ chomd +x hello.sh # 修改权限,加入可执行权限 (需转换到root下才可修改权限,利用 su root即可)
[hadoop1@hadoop1 test]$ ./hello.sh # 执行脚本,输出内容 hello world
第一种方法本质是利用bash解释器执行脚本,不需要可执行操作即可;第二种方法是脚本自己要执行,必须要有可执行权限。
二、变量
2.1、系统预定义变量
常用系统变量:$HOME主目录,$PWD当前路径,$SHELL解释器,$USER用户名
查看系统所有变量 set
- 查看系统变量
[hadoop1@hadoop1 test]$ echo $HOME
/home/hadoop1
[hadoop1@hadoop1 test]$ echo $PWD
/home/hadoop1/test
[hadoop1@hadoop1 test]$ echo $USER
hadoop1
[hadoop1@hadoop1 test]$ echo $SHELL
/bin/bash
2.2、自定义变量
-
定义变量:变量名=变量值,=前后不能有空格
-
撤销变量:unset 变量名
-
声明静态变量:readonly 变量,不能撤销静态变量,不能修改静态变量
-
将变量转为全局变量:export 变量名
注意:
变量名可以由字母、下划线和数字组成,但不能以数字开头;=两侧不能有空格;
在bash中,变量默认类型都是字符串类型,无法直接进行数值计算;
变量值若有空格,需使用单/双引号括起来。
-
定义变量A,给变量重新赋值,撤销变量A
# 定义变量A
[hadoop1@hadoop1 test]$ A=2
[hadoop1@hadoop1 test]$ echo $A
2
# 修改变量值
[hadoop1@hadoop1 test]$ A=6
[hadoop1@hadoop1 test]$ echo $A
6
# 撤销变量A
[hadoop1@hadoop1 test]$ unset A
[hadoop1@hadoop1 test]$ echo $A
[hadoop1@hadoop1 test]$
- 定义静态变量B,不能撤销,不能修改
# 定义静态变量B=1
[hadoop1@hadoop1 test]$ readonly B=1
[hadoop1@hadoop1 test]$ echo $B
1
# 修改静态变量,出错,静态变量只读,不可修改
[hadoop1@hadoop1 test]$ readonly B=3
bash: B: 只读变量
# 撤销静态变量,出错,同上
[hadoop1@hadoop1 test]$ unset B
bash: unset: B: 无法反设定: 只读 variable
单双引号的使用及区别
- 单引号:包围变量的值时,单引号里面是什么就输出什么,即使内容中有变量和命令(命令需要反引起来)也会把它们原样输出。这种方式比较适合定义显示纯字符串的情况,即不希望解析变量、命令等的场景。
- 双引号:包围变量的值时,输出时会先解析里面的变量和命令,而不是把双引号中的变量名和命令原样输出。这种方式比较适合字符串中附带有变量和命令并且想将其解析后再输出的变量定义。
- 1、引号的使用,带有空格的变量,不用引号会出错;
[hadoop1@hadoop1 test]$ s=hello world
bash: world: 未找到命令...
[hadoop1@hadoop1 test]$ s='hello world'
[hadoop1@hadoop1 test]$ echo $s
hello world
- 2、单引号与双引号
# 新建hello.sh,输入以下内容,分别用单引号和双引号赋值
>>
#!/bin/bash
s='hello world'
s1='${s}'
s2="${s}"
echo $s1
echo $s2
<<
# 读取数据
[hadoop1@hadoop1 test]$ ./hello.sh
${s}
hello world
2.3、特殊变量
2.3.1、 $n:输出第n个参数
$0:脚本名称
$1—$9:第1—9个参数
${10—}:第10个参数以上的,需要加大括号{}
# 文件hello.sh中有以下内容:
#!/bin/bash
echo $0
echo $1
echo $2
echo $3
# 输出hello.sh内容 并加入参数2,3
[hadoop1@hadoop1 test]$ ./hello.sh 2 3
./hello.sh
2
3
[hadoop1@hadoop1 test]$
2.3.2、 $#:获取参数的个数
$#:获取所有输入参数个数
[root@hadoop1 test]$ ./hello.sh 1 2 3 4
4
2.3.3、 $*, $@:代表所有参数
$*:代表命令行中的所有参数,把所有参数看成一个整体;
$@:代表命令行中的所有参数,把每个参数区分对待
[root@hadoop1 test]$ ./hello.sh 1 2 3 4
1 2 3 4
1 2 3 4
2.3.4、 $?:最后一次执行命令的返回状态
$?:最后一次执行的命令的返回状态;若为这个变量值为0,表明上一个命令正确执行;否则命令不正确
[hadoop1@hadoop1 test]$ echo $?
0
三、运算符
- 原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr。expr 最常用,expr是一款表达式计算工具,使用它能完成表达式的求值操作。
- 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边,反引号。
2.1、算数运算符
运算符 | 说明 | 举例 |
---|---|---|
+ | 加法 | `expr $a + $b` |
- | 减法 | `expr $a - $b` |
* | 乘法 | `expr $a * $b` |
/ | 除法,取整 | `expr $b / $a` |
% | 取余 | `expr $b % $a` |
= | 赋值 | a=$b 把变量 b 的值赋给 a |
== | 相等 | 用于比较两个数字,相同则返回 true。 [ $a == $b ] |
!= | 不相等 | 用于比较两个数字,不相同则返回 true。 [ $a != $b ] |
- 条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 [ $a == $b ]。
[hadoop1@hadoop1 test]$ A=6
[hadoop1@hadoop1 test]$ B=4
[hadoop1@hadoop1 test]$ echo "A-B=`expr $A - $B`"
A-B=2
[hadoop1@hadoop1 test]$ echo "A+B=`expr $A + $B`"
A+B=10
[hadoop1@hadoop1 test]$ echo "A/B=`expr $A / $B`"
A/B=1
[hadoop1@hadoop1 test]$ echo "A%B=`expr $A % $B`"
A%B=2
[hadoop1@hadoop1 test]$ echo "A*B=`expr $A \* $B`" # \转义
A*B=24
# hello.sh中写有以下内容:判断A和B是否相等的。
# if then ** else ** fi 条件语句,后面讲。
#!/bin/bash
A=6
B=4
if [ $A == $B ];then
echo 'A=B'
else
echo 'A!=B'
fi
if [ $A != $B ];then
echo 'A!=B'
else
echo 'A=B'
fi
[hadoop1@hadoop1 test]$ ./hello.sh
A!=B
A!=B
2.2、关系运算符
- 关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
运算符 | 说明 | 举例 |
---|---|---|
-eq,equal | 检测两个数是否相等,相等返回 true | [ $a -eq $b ] |
-ne,not equal | 检测两个数是否不相等,不相等返回 true | [ $a -ne $b ] |
-gt,greater than | 检测左边的数是否大于右边的,如果是,则返回 true | [ $a -gt $b ] |
-lt,lesser than | 检测左边的数是否小于右边的,如果是,则返回 true | [ $a -lt $b ] |
-ge,greater or equal | 检测左边的数是否大于等于右边的,如果是,则返回 true | [ $a -ge $b ] |
-le,lesser or equal | 检测左边的数是否小于等于右边的,如果是,则返回 true | [ $a -le $b ] |
# hello.sh中写有以下内容:判断A和B是否相等,A是否大于B
#!/bin/bash
A=6
B=4
if [ $A -eq $B ];then
echo "$A -eq $B:A等于B"
else
echo "$A -eq $B:A不等于B"
fi
if [ $A -gt $B ];then
echo "$A -gt $B:A大于B"
else
echo "$A -gt $B:A不大于B"
fi
[hadoop1@hadoop1 test]$ ./hello.sh
6 -eq 4:A不等于B
6 -gt 4:A大于B
2.3、布尔运算符
运算符 | 说明 | 举例 |
---|---|---|
! | 非运算,表达式为 true 则返回 false,否则返回 true | [ ! false ] |
-o | 或运算,有一个表达式为 true 则返回 true | [ $A -ne $B -o $A -ge $B ] |
-a | 与运算,两个表达式都为 true 才返回 true | [ $A -ge $B -a $A -eq $B ] |
#!/bin/bash
A=6
B=4
if [ $A -ne $B -o $A -ge $B ];then # A!=B or A>=B > true or true > true
echo "TRUE"
else
echo "FALSE"
fi
if [ $A -ge $B -a $A -eq $B ];then # A>=B and A=B > true and false > false
echo "TRUE"
else
echo "FALSE"
fi
[hadoop1@hadoop1 test]$ ./hello.sh
TRUE
FALSE
2.4、逻辑运算符
- 和-a ,-o 类似;不同的是需加两个中括号 即[[]]
运算符 | 说明 | 举例 |
---|---|---|
&& | 逻辑的 AND | [[ $a -lt 100 && $b -gt 100 ]] |
|| | 逻辑的 OR | [[ $a -lt 100 || $b -gt 100 ]] |
#!/bin/bash
A=6
B=4
if [[ $A -ne $B || $A -ge $B ]];then
echo "TRUE"
else
echo "FALSE"
fi
if [[ $A -ge $B && $A -eq $B ]];then
echo "TRUE"
else
echo "FALSE"
fi
[hadoop1@hadoop1 test]$ ./hello.sh
TRUE
FALSE
2.5、字符串运算符
运算符 | 说明 | 举例 |
---|---|---|
== | 检测两个字符串是否相等,相等返回 true | [ $a = $b ] |
!= | 检测两个字符串是否不相等,不相等返回 true | [ $a != $b ] |
-z | 检测字符串长度是否为0,为0返回 true | [ -z $a ] |
-n | 检测字符串长度是否不为 0,不为 0 返回 true | [ -n “$a” ] |
$ | 检测字符串是否为空,不为空返回 true | [ $a ] |
> | 大于,判断字符串时根据ASCII 码表顺序,不常用 | [ “name” > “age”] |
< | 小于,判断字符串时根据ASCII 码表顺序,不常用 | [ “name” > “age”] |
>= | 大于等于 | [ 3 > 6 ] |
<= | 小于等于 | [ 4 > 3 ] |
#!/bin/bash
A='name'
B='age'
if [ $A = $B ];then
echo "$A=$B:字符串相等"
else
echo "$A=$B:字符串不相等"
fi
if [ -n $A ];then
echo "-n $A:字符串长度不为0"
else
echo "-n $A:字符串长度为0"
fi
if [ $A ];then
echo "$A:字符串不为空"
else
echo "$A:字符串为空"
fi
[hadoop1@hadoop1 test]$ ./hello.sh
name=age:字符串不相等
-n name:字符串长度不为0
name:字符串不为空
2.6、文件测试运算符
操作符 | 说明 | 举例 |
---|---|---|
-b file | 检测文件是否是块设备文件 | [ -b $file ] |
-c file | 检测文件是否是字符设备文件 | [ -c $file ] |
-d file | 检测文件是否是目录 | [ -d $file ] |
-f file | 检测文件是否是普通文件(既不是目录,也不是设备文件) | [ -f $file ] |
-g file | 检测文件是否设置了 SGID 位 | [ -g $file ] |
-k file | 检测文件是否设置了粘着位(Sticky Bit) | [ -k $file ] |
-p file | 检测文件是否是有名管道 | [ -p $file ] |
-u file | 检测文件是否设置了 SUID 位 | [ -u $file ] |
-r file | 检测文件是否可读 | [ -r $file ] |
-w file | 检测文件是否可写 | [ -w $file ] |
-x file | 检测文件是否可执行 | [ -x $file ] |
-s file | 检测文件是否为空(文件大小是否大于0) | [ -s $file ] |
-e file | 检测文件(包括目录)是否存在 | [ -e $file ] |
-S file | 判断某文件是否 socket | [ -S $file ] |
-L file | 检测文件是否存在并且是一个符号链接 | [ -L $file ] |
#!/bin/bash
file1='./a'
file2='./a.txt'
if [ -d $file1 ];then
echo "$file1:是目录"
else
echo "$file1:不是目录"
fi
if [ -e $file2 ];then
echo "$file2:存在"
else
echo "$file2:不存在"
fi
[hadoop1@hadoop1 test]$ ./hello.sh
./a:是目录
./a.txt:不存在
2.7、其它运算符号
命令 | 描述 | 例子 |
---|---|---|
let | 整数运算,赋值并运算,支持++,– | let VAR=(1+2)*3 ; echo $VAR; |
expr | 整数运算,空格隔开,乘法*需要加反斜杠转义* | expr 1 * 2;;expr ( 1 + 2 ) * 2 |
bc | 计算器,支持浮点运算、平方等 | echo “1.2+2” |
[hadoop1@hadoop1 test]$ echo `expr 8+7`
8+7
[hadoop1@hadoop1 test]$ echo `expr 8 + 7`
15
[hadoop1@hadoop1 test]$ echo `expr 8 * 7`
expr: 语法错误
[hadoop1@hadoop1 test]$ echo `expr 8 \* 7`
56
[hadoop1@hadoop1 test]$ echo 2*(9-7)-6
2*(9-7)-6
[hadoop1@hadoop1 test]$ echo 2*(9-7)-6.4 | bc
-2.4
[hadoop1@hadoop1 test]$ let a=9*(3.2-6)-8;echo $a
bash: let: a=9*(3.2-6)-8: 语法错误: 无效的算术运算符 (错误符号是 ".2-6)-8")
-113
[hadoop1@hadoop1 test]$ let a=9*(3-6)-8;echo $a
-35