Linux | shell编程

§1 SHELL 是什么

shell 是一个命令行解释器,它为用户提供了一个向 Linux 内核发送请求以便云心程序的界面系统级成程序,用户可以用 SHELL 启动、挂起、停止、编写一些程序
在这里插入图片描述


§2 shell 的头、执行、注释

§2.1 头

shell 以 #!/bin/bash 或 #!/bin/sh 开头

#! 不是注释,是一个特殊符号,用于指定 shell 脚本解释器的路径
通常,sh 会软连接至 bash,并开启 POSIX 标准模式,相当于 #!/bin/bash --posix

§2.2 执行

脚本的执行
shell 脚本有以下三种执行方式:

  • 使用脚本绝对路径执行,脚本需要具有执行权限
    在这里插入图片描述
  • 使用脚本相对路径执行,脚本需要具有执行权限
    在这里插入图片描述
    在这里插入图片描述
  • sh 脚本执行,脚本不需要执行权限
    在这里插入图片描述

脚本的后台执行

./play.sh &

脚本的后台执行同时输出重定向

nohup ./play.sh >output 2>&1 &

linux 中三个标准流

  • 0:标准输入流 stdin
  • 1:标准输出流 stdout
  • 2:标准错误流 stderr

nohub 指令

  • 默认在当前目录下,输出一个名叫 nohup.out 的文件
  • 使用 > 文件 重定向 nohub 的输出 ,>文件 其实是 1>文件 的简写
  • 使用 流1> &流2 可以重定向流(引用流的目的或源),如 2>&1,表示标准错误流的输出位置引用当前的标准输出流
  • 2>1 表示标准错误流的输出位置是文件 1
§2.3 注释

按惯例,分为单行注释和多行注释

  • 单行注释
 # 被注释的一行语句
  • 块注释
:<<!
被注释的多行语句
被注释的多行语句
被注释的多行语句
!

在这里插入图片描述


§3 变量

变量分类
在 shell 中,可以使用以下几类变量

  • 系统变量
  • 用户自定义变量
  • 脚本参数变量
  • 预定义变量
§3.1 系统变量

系统变量也叫环境变量,下表为常见 系统变量,可以用 set 指令显示所有 系统变量

变量含义
$BASH展开为调用bash实例时使用的全路径名
$CDPATHcd命令的搜索路径。它是以冒号分隔的目录列表,shell通过它来搜索cd命令指定的目标目录。例如.:~:/usr
$EDITOR内置编辑器emacs、gmacs或vi的路径名
$ENV每一个新的bash,shell(包括脚本)启动时执行的环境文件。通常赋予这个变量的文件名是.bashrc。
$EUID展开为在shell启动时被初始化的当前用户的有效ID
$GROUPS当前用户所属的组
$HISTFILE指定保存命令行历史的文件。默认值是~/.bash_history。如果被复位,交互式shell退出时将不保存命令行历史
$HISTSIZE记录在命令行历史文件中的命令数。默认是500
$HOME主目录。未指定目录时,cd命令将转向该目录
$IFS内部字段分隔符,一般是空格符、制表符和换行符,用于由命令替换,循环结构中的表和读取的输入产生的词的字段划分
$LANG用来为没有以LC_开头的变量明确选取的种类确定locale类
$OLDPWD前一个工作目录
$PATH命令搜索路径。一个由冒号分隔的目录列表,shell用它来搜索命令,一个普通值为 /usr/gnu/bin:/usr/local/bin:/usr/ucb:/usr/bin
$PPID父进程的进程ID
$PS1主提示符串,默认值是$
$PS2次提示符串,默认值是>
$PS3与select命令一起使用的选择提示符串,默认值是#?
$PS4当开启追踪时使用的调试提示符串,默认值是+。追踪可以用set –x开启
$PWD当前工作目录。由cd设置
$RANDOM每次引用该变量,就产生一个随机整数。随机数序列可以通过给RANDOM赋值来初始化。如果RANDOM被复位,即使随后再设置,它也将失去特定的属性
$REPLY当没有给read提供参数时设置
$SHELL当调用shell时,它扫描环境变量以寻找该名字。shell给PATH、PS1、PS2、MAILCHECK和IFS设置默认值。HOME和MAIL由login(1)设置
$SHELLOPTS包含一列开启的shell选项,比如braceexpand、hashall、monitor等
$UID展开为当前用户的用户ID,在shell启动时初始化

设置系统变量

  • 声明:export 系统变量名=值
  • 生效:使用 source /etc/profile 指令命令使系统变量生效
  • 引用:$系统变量名
§3.2 用户自定义变量

声明/赋值、引用、销毁、引用命令执行结果

  • 声明一般变量:变量名=值
    • 变量名可以由 字母、数字、下划线组成,但不能由数字开头
    • = 两边不能有空格
    • 变量名通常大写
  • 声明静态变量:readonly 变量名 = 值,静态变量不能销毁
  • 引用变量的值:$变量名
  • 引用命令执行结果
    • 变量名=`命令`
    • 变量名=$(命令)
  • 销毁变量:unset 变量名
#!/bin/bash
A=111
readonly B=222
echo "a=$A"
echo "b=$B"
unset A
unset B
echo "a=$A"
echo "b=$B"

在这里插入图片描述

#!/bin/bash
A=`ls -l /home`
B=$(ls -l /root)

echo "A=$A"
echo "B=$B"

在这里插入图片描述

§3.3 脚本参数变量

执行脚本时,需要使用命名,并可能带有参数
若希望对命令本身和参数进行操作,可以使用 脚本参数变量
常见语法

  • $n/${n}:n 是数字
    • n=0,表示命令本身,不带参数
    • n∈(1-9),表示命令的第 1 - 第 9 个参数
    • n>=10,使用 ${n},表示命令的第 n 个参数
  • $* :所有参数,作为整体,与 $@ 区别见 §5.3.1 示例
  • $@:所有参数,作为数组,与 $* 区别见 §5.3.1 示例
  • $#:参数个数
#!/bin/bash
echo "指令本身 	$0"
echo "第二个参数 	$2"
echo "所有参数 	$*"
echo "所有参数 	$@"
echo "参数个数	$#"

在这里插入图片描述

§3.4 预定义变量

下列符号为预定义变量

  • $$:当前进程号
  • $!:后台运行的最后一个进程的进程号
  • $?:上一个命令的执行状态
    • 返回 0,上条命令执行正确
    • 返回 非0,上条命令执行不正确,但具体返回什么随不同命令变化
#!/bin/bash

# 输出当前进程号
echo "$$"

# 将一个脚本后台运行
./beplaied &
# 输出后台运行的最后一个进程号
echo "$!"

# 随便执行一个指令
cd /root
# 查看刚刚执行的指令是否成功
echo "$?"

在这里插入图片描述


§4 表达式与运算符

表达式主要可以分为

  • 运算表达式
  • 判断表达式
§4.1 运算表达式

运算表达式的基本形式

  • $((表达式))
  • $[表达式]
  • expr 表达式,expression,expr 与表达式之间需要空格,表达式的运算符两边也要有空格

运算表达式中的基本运算符

  • + 加
  • - 减
  • \* 乘,需要转义
  • / 除
  • % 取余
  • ++/-- 自增/自减,只能在 for(()) 中使用
#!/bin/bash

# $((3+2)) == 5
# $[$((3+2))*2] == 5*2 == 10
# expr $[$((3+2))*2] \* 5 == 50
# expr 与表达式之间需要空格,这个表达式的运算符两边也要有空格
echo "`expr $[$((3+2))*2] \* 5`"
# 求两个入参之和
echo $[$1+$2]

在这里插入图片描述

§4.2 判断表达式

判断表达式的基本形式:

  • [ 表达式 ]
    • 表达式与 [] 之间必须带空格
    • 关键字与 [] 之间必须带空格
  • [[ 表达式 ]]
    • 含义等同于 [ 表达式 ]
    • 使用 == 比较字符串时有不同含义,详见下面基本逻辑运算符
  • [ 表达式 ] && 语句1 || 语句2,三元运算符

基本逻辑运算符:

  • 整数比较
    • = 等于,[ 数字1 = 数字2 ],下同
    • -lt 小于
    • -le 小于等于
    • -gt 大于
    • -ge 大于等于
    • -ne 不等于
  • 字符串比较
    • = 等于,[ 字符串1 = 字符串2 ]
    • == 等于,基本和 = 相同,但有歧义,以 “$A” == a* 为例
      • [ “$A” == a* ] 用于判断 A 是否就是字符串 “a*”
      • [[ “$A” == a* ]] 用于判断 A 是否以 a 开头
    • -n 非空,字符串长度不为 0
    • -z 为空,字符串长度为 0
  • 权限比较
    • -r 有读权限,[ -r 文件或目录 ],下同
    • -w 有写权限
    • -x 有执行权限
  • 文件比较
    • -e 文件存在,[ -e 文件或目录 ],下同
    • -f 文件存在,且是个文件
    • -d 文件存在,且是个目录
  • 参数比较
    • if [ 参数 ] 参数不为空
    • if [ ! -n “参数” ] 参数为空
#!/bin/bash

# 字符串比较,注意表达式两侧的空格
[ "aaa" = "aaa" ] && echo "true" || echo "false"
# 数字比较
[ 1 -ge 2 ] && echo "true" || echo "false"
# 权限比较
[ -r /shell/play ] && echo "true" || echo "false"
# 文件比较
[ -d /shell ] && echo "true" || echo "false"

在这里插入图片描述


§5 流程控制

按惯例分为:

  • 顺序结构
  • 选择结构
  • 循环结构
§5.1 顺序结构(略)

不略没有天理 [手动捂脸]

§5.2 选择结构
§5.2.1 if

基本语法 – 形式1,行数少,但细看反人类

# 形式1
if [ 判断表达式 ] ;then
	代码1
else 代码2
fi

注意:

  • if 和 [] 之间需要空格
  • 表达式和 [] 之间需要空格
  • if 和 fi 不能在同一行
  • 没有 else 时,表达式1 不需要换行
#!/bin/bash
# 形式1
if [ $1 -gt $2 ];then echo "true"  
else echo "false"
fi

在这里插入图片描述

基本语法 – 形式2,省略分号,每个关键字都换行

# 形式2
if [ 判断表达式1 ]
then
	代码1
elif [ 判断表达式2 ] 
then
	代码2
else
	代码3
fi
	
#!/bin/bash
# 形式2
if [ $1 -gt $2 ]
then
	echo "if"
elif [ $1 -lt $2 ] 
then
	echo "elif"
else
	echo "else"
fi

在这里插入图片描述

§5.2.2 case

基本语法:

case $变量名 in
匹配值1)
代码1
;;
匹配值2)
代码2
;;
匹配值3)
代码3
;;
esac

说明:

  • case 最后一个匹配值后的双分号(;;)可以不写
  • 匹配值可以使用 “” 包裹,但省略不影响执行效果,但推荐带引号
  • case 可以实现与参数的对比,而不是只能和常量对比
#!/bin/bash
# 字符串形式
case $1 in
"1")
echo "比字符串"
esac

# 数字形式
case $2 in
2)
echo "比数字"
esac


# 参数
case $1 in
"$2")
echo "最后一个判断后的 ;; 可以不写"
;;
$3)
echo "比参数"
esac

在这里插入图片描述

§5.3 循环结构
§5.3.1 for-in

基本语法:

for 变量 in 数组
do
	代码
done
#!/bin/bash
# 省略式
echo "============无==========="
for i
do 
	echo $i
done

# 不带引号 $*,怀疑非法表达,解释为 省略式
echo "============\$*==========="
for i in $*
do 
	echo $i
done

# 不带引号 $@,怀疑非法表达,解释为 省略式
echo "============\$@==========="
for i in $@
do 
	echo $i
done

# 带引号 $*,参数列表作为整体字符串
echo "============\"\$*\"==========="
for i in "$*"
do 
	echo $i
done

# 带引号 $@,参数列表作为数组
echo "============\"\$@\"==========="
for i in "$@"
do 
	echo $i
done

在这里插入图片描述

§5.3.2 for(())

基本语法:

for((初始化;条件判断;变量判断))
do 
	代码
done
#!/bin/bash
for((i=0;i<10;i++))
do 
	SUM=$[ $SUM + $i ]
done
echo $SUM

在这里插入图片描述

§5.3.3 while
while [ 判断表达式 ]
do
	代码
done
#!/bin/bash
SUM=0
i=0

while [ $i -le $1 ]
do 
	SUM=$[$SUM+$i]
	i=$[$i+1]
done
echo $SUM

在这里插入图片描述

§5.4 控制台输入

命令:read 选项 变量
说明
选项说明:

  • -p:等待输入时的提示符(提示语)
  • -t:等待输入时的最大等待时间,单位秒
#!/bin/bash
# 不带时间
read -p "press some key: " INPUT
echo "input = $INPUT" 

# 带时间输入
read -t 3 -p "press some key: " WAIT
if [ ! -n "$WAIT" ] ;then WAIT="null"
fi
echo "wait for $WAIT"
# 带时间不输入
read -t 3 -p "press some key: " WAIT
if [ ! -n "$WAIT" ] ;then 
WAIT="null"
echo ""
fi
echo "wait for $WAIT"

在这里插入图片描述


§6 函数

§6.1 系统函数
§6.1.1 basename

指令:basename pathname suffix 截断前缀,相当于截取文件/目录名
说明:

  • 会将 pathname 的最后一级(最后一个 / 右侧),作为字符串返回
    • 若 pathname 是文件,只剩文件名
    • 若 pathname 是目录,只剩最后一级目录名
  • 可以指定 suffix,此时会额外将 suffix 的内容作为后缀截取,但若截取后是空,则忽略
#!/bin/bash

# 截取文件前缀
name=$(basename /sheell/beplaied.sh)
echo $name

# 截取文件前缀,若以 sh 结尾,则作为后缀截取
name=$(basename /sheell/beplaied.sh sh)
echo $name

# 截取目录前缀
name=$(basename /sheell)
echo $name

# 截取目录前缀
name=$(basename /sheell ll)
echo $name

在这里插入图片描述

§6.1.2 dirname

指令:dirname pathname 截取前缀,相当于截取文件/目录所在的上级目录路径
说明:

  • 会将 pathname 的最后一级之前,作为字符串返回,相当于返回上级目录
  • 可以指定 suffix,此时会额外将 suffix 的内容作为后缀截取,但若截取后是空,则忽略
#!/bin/bash

# 截取文件前缀
name=$(dirname /sheell/beplaied.sh)
echo $name

# 截取目录前缀
name=$(dirname /sheell)
echo $name

在这里插入图片描述

§6.2 自定义函数
§6.2.1 语法

格式:

# 声明
function function_name(){
	代码
}
# 调用
function_name 参数...

说明:

  • 声明函数时,不需要写形参
  • 函数可以有返回值,但返回值必须是数字
  • 执行函数后,可以用 $? 获取返回值,而不能用变量直接接收
    • 执行函数并返回后,若需要使用返回值,则不可在使用前执行任何语句,否则 $? 会获取这个语句的执行结果
    • 函数的返回值,宜用来表示函数执行的状态,即是否成功
    • 函数的执行效果,宜在函数中输出,或赋予变量,并通过变量使用
# 返回字符参
function a(){
	MSG="hahahaha: $1"
}
a $1
echo ${MSG}
# 返回数字
function a(){
	return $[$1*2]
}
$(a $1)
echo $?
echo $?

在这里插入图片描述

$9 语法注意事项

空格总结

语法款项空格
赋值= 两侧(SUM=$SUM+1)禁止
运算表达式expr 与 表达式之间(expr 1 + 1)必带
运算表达式expr 的表达式中运算符两侧(expr 1 + 1)必带
判断表达式表达式与 [] 之间([ 1 -le 2 ])必带
判断表达式关键字与 [] 之间(if [ $i -le 10 ])必带
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值