1、认识shell
shell是一个命令解释器,用于用户于Linux系统进行交互
shell介于用户和Linux内核之间,起到对内核的保护作用,所以用户先将命令输入完成后,交给shell来识别,将识别成功的命令转换为指令传递给linux内核。实现用户与操作系统的交互
2、shell类型
1、Bourne Shell(简称sh)
它是Unix的第一个Shell程序,早已成为工业标准。目前几乎所有
的Linux系统都支持它。不过Bourne Shell的作业控制功能薄弱,
且不支持别名与历史记录等功能。目前大多操作系统是将其作为
应急Shell使用
2、 C Shell(简称csh)
最初开发的目的是改进Bourne Shell的一些缺点,并使Shell脚本
的编程风格类似于C语言,不过C Shell的健壮性不如Bourne Shell。
3、 Korn Shell(简称ksh)
解决了Bourne Shell的用户交互问题,并克服了C Shell的脚本编程
怪癖的缺点。Korn Shell的缺点是需要许可证,这导致它应用范围
不如Bourne Shell广泛
4、Bourne Again Shell(简称bash)
Bourne Again Shell由AT&T贝尔实验室开发,是Bourne Shell的增强版。
随着几年的不断完善,已经成为最流行的Shell。它包括了早期的Bourne
Shell和Korn Shell的原始功能,以及某些C Shell脚本语言的特性。
此外,它还具有以下特点:能够提供环境变量以配置用户Shell环境,
支持历史记录,内置算术功能,支持通配符表达式,将常用命令内置简化。
3、shell命令格式
$ Command [-Options] Argument1 Argument2 …
指令 选项 参数1 参数2…
注意:
一条命令的三要素之间用空格隔开;
若将多个命令在一行书写,用分号(;)将各命令隔开;
如果一条命令不能在一行写完,在行尾使用反斜杠(\)标明该条命令未结束。
4、shell中bash的特点
1、 补全命令
在使用shell命令时,几乎所有的命令和命令后面跟的存在的文件名,都可以通过tal键补全
2 、命令历史记录
当前linux 操作系统下输入的shell命令都会保存起来,可以通过上下键访问到之前输入的命··· 令,实际所有的输入过的命令保存在家目录下的.bash_history文件中
3、 alias命令 对命令取别名
alias 显示当前已经取别名的命令
临时设置命令的别名:
alias LSL=‘ls; ls -l’
永久设置:
在家目录下的.bashrc中输入alias命令即可
设置完毕后需要输入命令source .bashrc,重新设置配置文件
4 、特殊符号
(1)通配符
用于处理多个文件
星号" * " 匹配任意长度的字符串
问号" ? " 匹配一个长度的字符
方括号" […] " 匹配其中指定的一个字符
方括号" [ - ] " 匹配指定的一个字符范围
方括号" [^…] " 除了其中指定的字符,均可匹配
(2)管道符 |
命令1 | 命令2
命令1的输出结果作为命令2的输入,
可以理解为将命令1的输出结果看做是文件的内容,命令2就是对文件的操作
注意:命令1必须是有输出的命令
例子:
ls /etc | wc -w
ls -l /etc | more
(3)输入/输出重定向
输出重定向:将输出的终端的数据重定向写入一个文件里面
> file 将>左边的输出到终端的内容写入file文件
如果文件不存在则创建,如果文件存在则清空后再写入
例子:
echo "hello world" > file.txt
ls /etc > file.txt
>> file 将>>左边的输出到终端的内容写入file文件
如果文件不存在则创建,如果文件存在则追加写入数据
2> 或 &>
2>> 或者 &>> 如果命令输出错误进行重定向
例如:
ls asdfasd 2> file.txt 将命令执行的错误信息写入文件
输入重定向:将原本从终端获取的数据从文件里面获取
< file 将file文件重定向为输入源
例如:
wc < file.txt
5、shell脚本
1、shell脚本语言是解释型语言,不需要进行编译
shell脚本的本质:shell命令的有序集合
shell脚本文件后缀为 .sh
# #用于注释一行
# #!标识当前文件里面所有的命令通过那个shell类型来解释,所以后面跟shell类型的路径
#! /bin/bash
#shell脚本:shell命令的有序集合,所以都是命令
echo "hello world"
date
ls
ls -l
pwd
赋予文件执行权限
chmod +x *.sh
执行文件
./*.sh 或者 bash *.sh
2、shell变量
shell允许用户建立变量存储数据,但不支持有数据类型,变量赋予任何值都会被解释为一串字符
1、变量的定义和赋值
变量名=值
注意:等号两边一定不能有空格;
Bourne Shell有如下四种变量:
1.用户自定义变量
2.位置变量即 命令行参数 预定义变量
3.环境变量
命令行输入下列命令能查看
set 查看所有的变量,包括环境变量,
env 查看环境变量
2、用户自定义变量
(1)shell里面的特殊字符
$ 获取一个变量的值 $A
# 使用#来注释内容
' ' 使用单引号引起来的内容,特殊字符没有特殊含义
" " 使用双引号引起来的内容,特殊字符没有特殊含义,除了$ ` \以外
``或者$() 命令置换,获取一个输出命令的结果
\ 反斜杠后面的特殊字符失去特殊含义
-n 表示输出文字后不换行
-e 支持反斜控制的字符转换
\n 换行
\t 制表符
例如
#! /bin/bash
#定义一个变量
A=100
#使用echo输出变量的值
#$:标识获取一个变量的值
echo $A
#echo -n 不换行
echo -n $A
echo ""
#-e 如果echo后跟-e,则可以使用\n来换行
echo -n -e "hello world\t$A\n"
#shell中的特殊字符
VAL="hello world"
echo $VAL
#'':单引号里面的特殊字符失去特殊含义
echo '$VAL'
#"":双引号里面的特殊字符没有特殊含义,除了$ ` \
echo "$VAL"
#\:反斜杠后面的特殊字符将失去特殊含义
echo "\$VAL = $VAL"
echo \'$VAL\'
#将一个变量的值赋值给另一个变量,需要加$
B=$A
echo "B = $B"
#使用unset清空一个变量的值
unset B
echo "B = $B"
3、环境变量
shell在开始执行时就已经定义了一些和系统的工作环境有关的变量,我们在shell中可以直接使用。
export PATH=$PATH:/usr/local/go/bin
echo $PATH
一般情况下,所有环境变量均为大写。
环境变量可以在任意一个自己定义的脚本文件当中使用
如果在终端设置环境变量,此时是临时的,并且只能在当前终端使用,
如果想永久使用,需要在./.bashrc或者/etc/profile中设置环境变量并更新就可以永久使用
3、位置变量
$0 与键入的命令行一样,包含脚本文件名
$1,$2,……$9 分别包含第一个到第九个命令行参数
${10}… 10以上需要加{}
$# 包含命令行参数的个数
$@ 包含所有命令行参数:“$1,$2,……$9”
$? 包含前一个命令的退出状态,非0即为执行失败
$* 包含所有命令行参数:“$1,$2,……$9”
$$ 包含正在执行进程的ID号
#! /bin/bash
#位置变量$0 - $9 保存从终端输入的每一个参数
echo "\$0 = $0"
echo "\$1 = $1"
echo "\$2 = $2"
echo "\$5 = $5"
echo "\$6 = $6"
echo "\$7 = $7"
echo "\$8 = $8"
echo "\$9 = $9"
#如果查过9,需要加{}
echo "\$10 = ${10}"
echo "\$11 = ${11}"
#$#:保存命令行传入的参数的个数,不包括$0
echo "\$# = $#"
#$@或者$*:保存所有的命令行传入的参数,但是不包括$0
echo "\$@ = $@"
echo "\$* = $*"
#$$:获取当前进程的进程号
echo "\$$ = $$"
#read A
#$?:返回上一个命令的执行结果,如果执行成功值为0,失败值为非0
A=100
echo "\$? = $?"
ls
echo "\$? = $?"
ls adsfadsf
echo "\$? = $?"
2、shell语法
说明性语句:
以#开始到改行结束,该语句不被解释执行
功能性语句:
任意的shell命令、用户程序或其他shell程序。
结构性语句:
条件测试语句、多路分支语句、循环语句、循环控制语句等。
例如:
#! /bin/bash
#使用read命令获取终端输入的数据
:<<!
read A
echo "A = $A"
! #多行注释
:<<!
read A B C #获取终端输入的数据并赋给后面的变量
echo "A = $A"
echo "B = $B"
echo "C = $C"
!
#echo -n "please input two numbers >>> "
#read num1 num2
#-p:输出提示信息
#read -p "please input two numbers >>> " num1 num2
#-t:指定时间范围内输入,输入时间到达时没有输入完毕,则一个都不会赋值
#read -t 5 -p "please input two numbers >>> " num1 num2
#-n:指定字节数范围内输入,如果超过指定的字节数,立即结束输入,如果有空格,会赋值给多个变量,否则只会赋值给一个
#read -n 5 -p "please input two numbers >>> " num1 num2
#-s:隐藏输入的数据
read -s -p "please input two numbers >>> " num1 num2
echo "num1 = $num1"
echo "num2 = $num2"
算数运算
算术运算命令expr主要用于进行简单的整数运算,包括加(+)、减(-)、 乘(*)、整除(/)和求模(%)等操作。
#! /bin/bash
A=10
B=8
echo "$A + $B = `expr $A + $B`"
C=$(expr $A - $B)
echo "$A - $B = $C"
D=`expr $A \* $B`
echo "$A * $B = $D"
E=`expr $A / $B`
echo "$A / $B = $E"
F=`expr $A % $B`
echo "$A % $B = $F"
let M=$A+$B
echo "M = $M"
N=$(( $A - $B ))
echo "N = $N"
Y=$[$A * $B]
echo "Y = $Y"
3、shell控制语句
条件测试语句 if
多路分支语句 case
循环语句 for while until
辅助控制 break continue exit
if语句
形式1:
if [ 表达式 ]
then
命令表
fi
形式2:
if [ 表达式 ]
then
命令表1
else
命令表2
fi
形式3:
if [ 表达式1 ]
then
命令表1
elif [ 表达式2 ]
then
命令表2
...
else
命令表n
fi
例如:
#! /bin/bash
read -p "please input a number >>> " NUM
#注意:赋值时,等号两边不能加空格
# []里面存放表达式时必须加空格
:<<!
if [ $NUM -gt 50 ]
then
echo "NUM > 50"
fi
!
:<<!
if [ $NUM -gt 50 ]
then
echo "NUM > 50"
else
echo "NUM <= 50"
fi
!
if [ $NUM -gt 50 ]
then
echo "NUM > 50"
elif [ $NUM -eq 50 ]
then
echo "NUM = 50"
else
echo "NUM < 50"
if [ $NUM -gt 30 ]
then
echo "NUM > 30"
else
echo "NUM <= 30"
fi
fi
case语句
case $变量名 in
值1)
命令表2
;;
值2)
命令表2
;;
...
*)
命令表n
;;
esac
例如
#! /bin/bash
read -p "please input yes ot no >> " VALUE
case $VALUE in
yes | YES | Yes)
echo "yes"
;;
no | NO | No)
echo "no"
;;
*)
echo "input error"
;;
esac
for语句
for 变量名 in 单词表
do
命令表
done
#! /bin/bash
:<<!
for NUM in 1 2 3 4 5 6 7 8 9 10
do
echo "NUM = $NUM"
done
!
:<<!
for NUM in `ls`
do
echo "NUM = $NUM"
done
!
#shell里面的for循环也可以支持C语言的用法
for((NUM = 1; NUM <= 10; NUM++))
do
echo "NUM = $NUM"
done
while语句
while 命令或表达式
do
命令表
done
例如:
#! /bin/bash
NUM=1
SUM=0
while [ $NUM -le 100 ]
do
#echo "NUM = $NUM"
#NUM=`expr $NUM + 1`
SUM=`expr $SUM + $NUM`
NUM=`expr $NUM + 1`
done
echo "1 + 2 + 3 + ... + 100 = $SUM"
until语句
until 命令或表达式
do
命令表
done
他与while类似,只是把条件测试反过来了,换句话说,
循环将反复执行直到条件为真,而不是在条件为真的时候反复执行
例如:
#! /bin/bash
NUM=1
SUM=0
until [ $NUM -gt 100 ]
do
SUM=`expr $SUM + $NUM`
NUM=`expr $NUM + 1`
done
echo "1 + 2 + 3 + ... + 100 = $SUM"
4、shell函数
有些脚本段功能可能互相重复,如果能只写一次代码而在任何地方都能引用那么就提高了代码的可重用性。shell允许将一组命令集合或语句形成一个可用块,这些块成为shell函数。
定义函数的两种格式:
格式一:
函数名()
{
命令 ...
}
格式二:
function 函数名()
{
命令 ...
}
例如:
#! /bin/bash
#由于shell中没有主函数,所以函数一般定义在调用之前即可
#为了方便,一般将函数定义在shell脚本的最上方
#定义shell函数
myfun()
{
echo "hello world"
echo "nihao chengdu"
}
#函数的调用
myfun
myfun
myfun
返回值情况
#! /bin/bash
myadd()
{
A=$1
B=$2
SUM=`expr $A + $B`
#return $SUM
}
#shell函数的返回值,当函数调用结束后,通过$?获取函数的返回值
#但是,$?只能保存0~255之前的数,如果超过,就错误了
myadd 100 200
#echo "SUM = $?"
#注意:在shell脚本中,不管在哪定义变量,如果不做任何修饰,都是全局变量
#但是如果时函数中定义的变量,需要调用函数之后,才能使用变量
echo "SUM = $SUM"
break、continue、exit
#! /bin/bash
NUM=0
while [ $NUM -le 10 ]
do
let NUM++
if [ $NUM -eq 5 ]
then
#使用break可以结束整个循环
#break
#使用continue可以退出本层循环
#continue
#使用exit退出整个程序
exit
fi
echo "NUM = $NUM"
done
echo "hello world"
变量作用域
#! /bin/bash
#在shell中的变量,如果定义的时候不进行任何修饰,则不管在哪个位置,都是全局变量
#但是如果是函数内部定义的变量,如果要在函数外部使用,必须先调用
A=100
myfun()
{
B=200
#使用local修饰的变量称之为局部变量,局部变量只能在函数内部定义和使用
local C=300
echo "in myfun"
echo "A = $A"
echo "B = $B"
echo "C = $C"
}
echo "before myfun"
echo "A = $A"
echo "B = $B"
myfun
echo "after myfun"
echo "A = $A"
echo "B = $B"
echo "C = $C"