Shell概述
shell是一个命令行解释器,它接收应用程序/用户命令,然后调用操作系统内核
目录
一、脚本入门
脚本格式
脚本以#!/bin/bash开头(指定解析器)
查看系统支持的shell:
cat /etc/shells
# 创建脚本
[linux@localhost datas]$ cat helloworld.sh
#!/bin/bash
echo "hello huangxb"
# 执行脚本方式1
[linux@localhost datas]$ bash helloworld.sh
hello huangxb
# 执行脚本方式2
[linux@localhost datas]$ ./helloworld.sh
-bash: ./helloworld.sh: 权限不够
#脚本执行方式3
. helloworld.sh
source helloworld.sh
方式1,本质是bash解析器帮你执行脚本,所以脚本本身不需要执行权限;方式2,本质是脚本自己需要执行,所以需要执行权限
方式3, source命令也称为“点命令”,也就是一个点符号(.),是bash的内部命令。 功能:使Shell读入指定的Shell程序文件并依次执行文件中的所有语句 source命令通常用于重新执行刚修改的初始化文件,使之立即生效,而不必注销并重新登录。
方式3会在当前的Bash进程中执行,而方式1和方式2则是执行了bash这个命令,即开了一个新的Shell,方式3产生的临时变量后续可以继续使用,方式1和方式2产生的临时变量在脚本执行完后即注销。
多命令处理
- 在linux家目录下创建一个bangzhang.txt并在文件中写入"I IOVE YOU"字符
- ;在一行可以执行多个指令,以分号分开。
#!/bin/bash
cd /home/linux/
touch banzhang.txt
echo "I LOVE YOU" >> banzhang.txt
二、Shell中的变量
常用系统变量
$HOME $PWD $SHELL $USER
[linux@localhost datas]$ echo $HOME
/home/linux
[linux@localhost datas]$ echo $PWD
/home/linux/datas
[linux@localhost datas]$ echo $SHELL
/bin/bash
[linux@localhost datas]$ echo $USER
linux
env, set, export
env:显示所有的环境变量
set:显示所有本地定义的shell变量
export:把一个变量变作环境变量。export不加参数的时候,显示哪些变量被导出成了用户变量,一个shell自己的变量可以通过export “导出”变成一个用户变量(env和export显示基本一样,env多了一个_=/usr/bin/env)
关于哪些变量是环境变量,可以简单地理解成在当前进程的子进程有效则为环境变量,否则不是。
直接运行export命令定义变量【只对当前shell(BASH)有效(临时的)】
在shell的命令行下直接使用[export变量名=变量值]定义变量,该变量只在当前的shell(BASH)或其子shell(BASH)下是有效的,shell关闭了,变量也就失效了,再打开新shell时就没有这个变量,需要使用的话还需要重新定义。
自定义变量
基本语法
- 定义变量:变量=值 等号两边不能留有空格
- 撤销变量:unset 变量
- 输出变量:echo $变量
- 声明静态变量: readonly 变量,注意:不能unset
[linux@localhost datas]$ A=1
[linux@localhost datas]$ echo $A
1
[linux@localhost datas]$ unset A
变量定义规则
- 变量名称可以由字母,数字和下划线组成,不能以数字开头,环境变量名建议大写
- 等号两侧不能有空格
- 在bash中,变量默认类型都是字符串类型,无法直接进行数值运算
- 变量的值如果有空格,需要使用双引号或单引号括起来
[linux@localhost datas]$ D="A B C"
[linux@localhost datas]$ echo $D
A B C
- 可把变量提升为全局变量,可供其他shell程序使用
export 变量
特殊变量
$n (描述:n为数字,$0代表脚本名称,10以内参数用$1-9 表 示 , 10 以 上 的 需 要 用 大 括 号 包 含 , 9表示,10以上的需要用大括号包含,9表示,10以上的需要用大括号包含,{10})
#!/bin/bash
echo "$0 $1 $2 $3"
$# (功能描述:获取所有输入参数个数,常用于循环)
#!/bin/bash
echo "$0 $1 $2 $3"
echo $#
- $* (描述:代表命令行中所有的参数,把所有参数看成一个整体)
- $@ (描述:也代表命令行中所有的参数,不过把每个参数区分对待)
- for循环使用时需要用双引号"$@"
- 当它们被双引号“”包含时,“$*”会将所有的参数作为一个整体,以“$1 $2 …$n”的形式输出所有参数;“$@”会将各个参数分开,以“$1” “$2”…”$n”的形式输出所有参数。
-
将上次命令执行是否成功的返回值放到提示符里面去:
export PS1="[\$?]${PS1}"
[linux@localhost datas]$ bash parameter.sh test1 test2
parameter.sh test1 test2
2
test1 test2
test1 test2
$? (描述:最后一次执行命令的状态,0:正确执行)
运算符
- $((运算式)) 或 $[运算式]
- expr +,-,\*,/,% 加减乘除取余
expr运算符间要有空格
# 计算2+3
[linux@localhost datas]$ expr 2 + 3
5
# 计算(2+3)*4
## 方式1
[linux@localhost datas]$ expr `expr 2 + 3` \* 4
20
## 方式2
[linux@localhost datas]$ s=$[(2+3)*4]
[linux@localhost datas]$ echo $s
20
三、条件判断
基本语法
test condition
[condition] (注意 condition前后要有空格)
注意:条件非空即为 true,[ abcde ]返回 true,[] 返回 false。
常用判断条件
两个整数之间比较
符号 | 描述 |
---|---|
-lt | (less than)小于 |
-le | (less equal) 小于等于 |
-eq | (equal)等于 |
-gt | (greater than) 大于 |
-ge | (greater equal) 大于等于 |
-ne | (not equal) 不等于 |
字符串判断
= | 等于则为真 |
!= | 不相等则为真 |
-z 字符串 | 字符串的长度为零则为真 |
-n 字符串 | 字符串的长度不为零则为真 |
小技巧:
if [ "$1"x = "test"x ] ; then
左右两边的x用于保证判断时不会报错。如果没有定义$1,则进行 [ x = "test"x ]判断,不会报错。实际还是比较$1是否等于test。
[ "${BOARD_NAME}" ] || BOARD_NAME="$1" 这条语句的意思是如果BOARD_NAME这个变量是空的话(即前半部分条件判断返回为假),执行后边的赋值语句。
文件权限判断
- -r 有读的权限
- -w 有写的权限
- -x 有执行的权限
文件类型判断
- -f 文件存在并且是一个常规文件
- -e 文件存在
- -d 文件存在并是一个目录
# 判断23是否大于2
[linux@localhost datas]$ [ 23 -gt 2 ]
[linux@localhost datas]$ echo $?
0
# 判断helloworld.sh是否有写入权限
[linux@localhost datas]$ [ -w hellowrld.sh ]
[linux@localhost datas]$ echo $?
1
# 判断目录中文件是否存在
[linux@localhost datas]$ [ -e /home/linux/datas ]
[linux@localhost datas]$ echo $?
0
多条件判断
&& ||用于多个[ condition ]进行连接
[ condition ] && echo "exect ok" || echo "exect false"
条件为真则执行第一个指令,条件为假则执行第二条指令。
- 只有在 && 左边的命令返回真,&& 右边的命令才会被执行。
- 只要&& 有一个命令返回假(命令返回值 $? == 1),后面的命令就不会被执行。
- 只有在 || 左边的命令返回假,|| 右边的命令才会被执行。
- 只要|| 有一个命令返回真,后面的命令就不会被执行。
[ condition ] 条件表达式中可能有多个条件,需要使用与或非等逻辑操作。
-a 与
-o 或
! 非
四、流程控制
IF判断
注意:if 后要有空格
[linux@localhost datas]$ cat if.sh
#!/bin/bash
if [ $1 -eq 1 ]
then
echo "输入为1"
elif [ $1 -eq 2 ]
then
echo "输入为2"
fi
[linux@localhost datas]$ bash if.sh 2
输入为2
case 语句
[linux@localhost datas]$ cat case.sh
#!/bin/bash
case $1 in
1)
echo "班长"
;;
2)
echo "学习委员"
;;
*)
echo "体育委员"
;;
esac
[linux@localhost datas]$ bash case.sh 2
学习委员
for循环
语法1
[linux@localhost datas]$ cat for.sh
#!/bin/bash
s=0
for((i=1;i<=100;i++))
do
s=$[$s+$i]
done
echo $s
[linux@localhost datas]$ bash for.sh
5050
语法2
[linux@localhost datas]$ cat for2.sh
#!/bin/bash
for i in $*
do
echo $i
done
[linux@localhost datas]$ bash for2.sh 1 2
1
2
WHILE循环
[linux@localhost datas]$ cat while.sh
#!/bin/bash
s=0
i=1
while [ $i -le 100 ]
do
s=$[$s + $i]
i=$[$i + 1]
done
echo $s
[linux@localhost datas]$ bash while.sh
5050
五、函数
read读取控制台输入
read(选项)(参数)
- -p 指定读取值时的提示符
- -t 指定读取值时等待的时间(秒)
# 提示7秒内,读取控制台输入的名称
[linux@localhost datas]$ cat read.sh
#!/bin/bash
read -t 7 -p "在7s内请输入你的名字" NAME
echo $NAME
[linux@localhost datas]$ bash read.sh
在7s
系统函数
basename [string / pathname] [suffix] (描述:basename命令会删掉所有的前缀包括最后一个‘/’字符,然后将字符串显示出来)
# 方式1
[linux@localhost datas]$ basename /home/linux/banzhang.txt
banzhang.txt
# 方式2
[linux@localhost datas]$ basename /home/linux/banzhang.txt .txt
banzhang
dirname 文件绝对路径 (描述:从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分))
[linux@localhost datas]$ dirname /home/linux/banzhang.txt
/home/linux
自定义函数
(1)必须在调用函数地方之前,先声明函数,shell 脚本是逐行运行。不会像其它语言一样先编译。
(2)函数返回值,只能通过$?系统变量获得,可以显示加:return 返回,return 后跟数值 n(0-255)。如果不加,将以最后一条命令运行结果,作为返回值return。
# 格式
[ function ] funname[()]
{
Action:
[return int;]
}
funname
# DESC 计算输入两个参数的值
[linux@localhost datas]$ cat sum.sh
#!/bin/bash
function sum(){
s=0;
s=$[$1 + $2]
echo $s
}
read -p "input your param1:" P1
read -p "input your param2:" P2
sum $P1 $P2
[linux@localhost datas]$ bash sum.sh
input your param1:1
input your param2:2
3
六、元字符
元字符是Shell的保留字符,在Shell中有着特殊的含义。
{0..100} 从0到100
七、shell常用指令
let
let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。
自加操作:let no++
自减操作:let no--
简写形式 let no+=10,let no-=20,分别等同于 let no=no+10,let no=no-20。
set
set命令可以定义脚本的运行方式,变量的获取方式,脚本的执行过程,脚本的测试。
set -u
检查脚本内的变量,如果有变量未被定义将终止脚本(脚本的自检测功能)
set -e
脚本遇到返回值非零的情况,也就是错误就退出。(可以认为这个是debug模式开启命令)
set -o pipefail
检测脚本内的组合命令----管道命令的debug模式,也就是需要配合set -e先行开启debug模式,然后在单独针对管道命令检测shell脚本的健壮性
set -x 和set +x
这两个为什么放到一起说呢?因为,这其实是一个显示脚本执行过程并将脚本内的变量的值暴露出来的一个开关,-x 是开,+x等于是默认的关闭,一般情况下,脚本是关闭这个显示过程的。
cut
cut命令从文件的每一行剪切字节,字符和字段并将这些字节,字符和字段输出
cut [选项参数] filename
- -f 列号,提取第几列
- -d 分隔符,按照指定分隔符分隔列
# DESC 切割cut.txt第一列
[linux@localhost datas]$ cat cut.txt
dong shen
guan zhen
wo wo
lai lai
le le
[linux@localhost datas]$ cut -d " " -f 1 cut.txt
dong
guan
wo
lai
le
# DESC 获取第三行第一个单词
[linux@localhost datas]$ cat cut.txt | grep guan | cut -d " " -f 1
guan
sed
sed是一种流编辑器,它一次处理一行内容,处理时,把当前处理的行存储在临时缓冲区中,成为“模式空间”,接着sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕,接着处理下一行,这样不断重复,知道文件末尾,文件内容并没有改变,除非你使用重定向存储输出
sed [选项参数] ‘command’ filename
- -e 直接在指令列模式上进行sed的动作编辑
命令功能描述
- a 新增
- d 删除
- s 查找并替换
# DESC 在第二行后增加mei nv字符
[linux@localhost datas]$ sed -e "2a mei nv" sed.txt
dong zhen
guan zhen
mei nv
wo wo
lai lai
awk
awk 一个强大文件分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理
awk [选项参数] 'pattern1 {action1} pattern2{action2}..' filename
- -F 指定输入文件分隔符
- -v 赋值一个用户定义变量
sort
sort 命令是在Linux里非常有用,它将文件进行排序,并将排序结果标准输出
sourt [选项] (参数)
参数 | 描述 |
---|---|
-n | 依照数值大小排序 |
-r | 以相反的顺序排序 |
-t | 设置排序时使用的分隔字符 |
-k | 指定需要排序的列 |