文章

Linux Shell编程

Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。
Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
Ken Thompson 的 sh 是第一种 Unix Shell,Windows Explorer 是一个典型的图形界面 Shell。

bash通配符介绍

通配符允许您简洁地指定用于匹配一组文件名的模式(例如,*.pdf 模式可以获得所有 PDF 文件列表)。通配符通常也被称为 glob 模式。但是,glob 模式的用途不仅仅只能生成一个有用的文件名列表。Bash man 帮助页面中将 glob 模式简单地称为 “Pattern Matching(模式匹配)”。

通配符描 述
*匹配任意长度的任何字符串,包括空字符串
?匹配任何单个字符
[…]匹配在指定字符范围内任何单个字符,简化写法[a-z]不区分大小写
?(pattern-list)匹配零个或一个指定模式的匹配项(extglob)
*(pattern-list)匹配零个或更多指定模式的匹配项(extglob)
+(pattern-list)匹配一个或更多指定模式的匹配项(extglob)
@(pattern-list)匹配其中一个指定模式的匹配项(extglob)
!(pattern-list)匹配任何不匹配指定模式的项目(extglob)
[^]匹配指定字符范围外的任意单个字符

部分已经设置好的字符类:

字符类说明
[:alnum:]所有字母和数字
[:alpha:]所有字符,包括大小写
[:blank:]所有水平空白字符
[:cntrl:]所有控制字符(不可打印)
[:digit:]所有数字,等价于 [0-9]
[:graph:]所有图形字符
[:lower:]所有小写字符
[:print:]所有可打印字符
[:punct:]所有标点符号
[:space:]所有水平和垂直空格
[:upper:]所有大写字符
[:xdigit:]所有十六进制字符
Tab Tab显示文件或命令补全的可能性
1
2
3
4
5
6
7
8
9
10
# 列出a开头的所有文件
ls a*
# 列出a开头一共3个字母的文件
ls a??
# 列出三个大写字母文件名的文件
ls [[:upper:]][[:upper:]][[:upper:]]
# 列出一个字母后跟三个数字的文件
ls [a-z][0-9][0-9][0-9]
# 列出不以a字母开头后跟三个数字的文件
ls [^a][0-9][0-9][0-9]

拓展:Bash中的组合键

键或组合键功能
Ctrl+A将光标移动到命令行开头
Ctrl+C结束正在运行的程序并返回提示符
Ctrl+D退出当前shell会话,相当于键入exit或logout
Ctrl+E将光标移动到命令行末尾
Ctrl+HGenerate backspace character
Ctrl+LClear this terminal
Ctrl+R查询命令历史记录
Ctrl+Z暂停一个程序
ArrowLeft and ArrowRight将光标在命令行上向左或向右移动一个位置,这样就可以在其他位置插入字符,而不仅仅是在开头和结尾
ArrowUp and ArrowDown浏览历史。转到要重复的行,如果需要编辑详细信息,按Enter键以节省时间
Shift+PageUp and Shift+PageDown浏览终端缓冲区(查看已“滚屏”的文本)
Tab命令或文件名补全;当有多种选择时,系统会发出声音或视觉铃声,如果选择太多,则会询问你是否都想看
Tab Tab显示文件或命令补全的可能性

Shell脚本

Shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用shell来启动、挂起、停止甚至是编写一些程序。

脚本的编写和执行

  • 脚本格式要求:
    • 1.脚本以#!/bin/bash开头,指定其解释器
    • 2.脚本需要有可执行权限
  • 脚本常用的执行方式:
    • 1.赋予脚本x权限,然后输入脚本的绝对路径或者相对路径执行,如./hello.sh
    • 2.指定sh,直接执行,如sh hello.sh 或者 bash hello.sh
1
2
#!/bin/bash
echo "hello,world"

Shell的变量

介绍

  1. Linux Shell的变量分为系统变量用户自定义变量
  2. 系统变量:$HOME$PWD$SHELL$USER
  3. 显示当前shell中所有的变量:set

变量定义

基本语法

1
2
3
4
5
6
# 定义变量
变量=# 撤销变量
unset 变量
# 声明静态变量,这种变量不能unset
readonly 变量

注意事项:
等号两侧不能有空格
变量名称严格区分大小写,一般大写
变量名称可由字母数字下划线组成,不可以数字开头

将命令的返回值赋给变量

1
2
3
4
# 反引号,运行里面的命令,并把结果返回给变量A
A=`date`
# 等价于反引号
A=$(date)

环境变量的设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 将shell变量输出为环境变量/全局变量
export 变量名=变量值
# 让修改后的配置信息立即生效
source 配置文件
# 查询环境变量的值
echo $变量名

# 输出所有环境变量,包括全局变量、局部变量
set
# 输出全局环境变量
env

#删除变量或函数
unset 变量名

位置参数变量

如果希望获取到命令行的参数信息,就可以使用位置参数变量

基本语法

  • $n:n为数字,$0为命令本身,$1-$9代表第1到9个参数,10以上需要用大括号,如${10}
  • $*:代表命令行中所有的参数,整体看待
  • $@:代表命令行中所有的参数,区分看待,使用双引号 " 包含时可以明显看到区别
  • $#:代表命令行中所有参数的个数

预定义变量

shell设计者事先已经定义好的变量

  • $$:当前进程的进程号(PID)
  • $!:后台运行的最后一个进程的进程号(PID)
  • $_:上次命令传递的最后一个参数
  • $?:最后一次执行的命令的返回状态
    这个变量的值为0,那么上一个命令正确执行,如果非0则不正确

拓展变量

  • result=${parameter:-word} 如果parameter为空,则word赋值给result,否则输出parameter
  • result=${parameter:=word} 如果parameter为空,则word赋值给result和parameter,否则输出parameter
  • result=${parameter:?word} 如果parameter为空,则word当做stderr输出,否则输出parameter
  • result=${parameter:+word} 如果parameter为空,什么都不做,否则word赋值给result

字符串

字符串(String)就是一系列字符的组合。字符串是 Shell 编程中最常用的数据类型之一(除了数字和字符串,也没有其他类型了)。

字符串有三种形式:

  • 由单引号' '包围的字符串:
    • 任何字符都会原样输出,在其中使用变量是无效的。
    • 字符串中不能出现单引号,即使对单引号进行转义也不行。
  • 由双引号" "包围的字符串:
    • 如果其中包含了某个变量,那么该变量会被解析(得到该变量的值),而不是原样输出。
    • 字符串中可以出现双引号,只要它被转义了就行。
  • 不被引号包围的字符串
    • 不被引号包围的字符串中出现变量时也会被解析,这一点和双引号” “包围的字符串一样。
    • 字符串中不能出现空格,否则空格后边的字符串会作为其他变量或者命令解析。
1
2
3
4
5
6
# 强引用,将字符串$(date)赋值给A
A='$(date)'
# 识别特殊符号,弱引用,将命令date的结果赋值给A
A="$(date)"
# 将命令date的结果赋值给A,连续的符号可使用,有空格则有歧义
A=$(date)

字符串拼接(连接、合并)

在 Shell 中你不需要使用任何运算符,将两个字符串并排放在一起就能实现拼接。请看下面的例子:

1
2
3
4
5
str1=$A$B  #中间不能有空格
str2="$A $B"  #如果被双引号包围,那么中间可以有空格
str3=$A": "$B  #中间可以出现别的字符串
str4="$A: $B"  #这样写也可以
str5="${A}is: ${B}"  #如果有字符串,需要给变量名加上大括号

字符串截取

格式说明
${变量}返回变量值
${#变量}返回变量长度,字符长度
${变量:start}从变量的左边第 start 个字符开始截取,直到最后。start 为正整数
${变量:start:length}从变量的左边第 start 个字符开始,向右截取 length 个字符。
${变量:0-start}从变量的右边第 start 个字符开始截取,直到最后。
${变量:0-start:length}从变量的右边第 start 个字符开始,向右截取 length 个字符。
${变量#word}从变量开头,删除最短匹配的word
${变量##word}从变量开头,删除最长匹配的word
${变量%word}从变量结尾开始,删除最短匹配的word
${变量%%word}从变量结尾开始,删除最长匹配的word
${变量/pattern/string}用 string 代替第一个匹配的 pattern。
${变量//pattern/string}用 string 代替所有 pattern。

多行注释

1
2
3
:<<!
注释内容
!

运算符

基本语法

  1. $((运算式))$[运算式]expr m + n
  2. 注意expr运算符间要有空格,如果希望将expr的结果赋给变量,使用反引号
  3. 乘:\*(在使用expr时需要转义)
    除:/
    取余:%

条件判断

基本语法 [ condition ](注意前后要有空格)
只要非空即返回true

常用判断条件

  • 字符串比较(=
  • 两个整数的比较
    • -lt(小于)
    • -le(小于等于)
    • -eq(等于)
    • -gt(大于)
    • -ge(大于等于)
    • -ne(不等于)
  • 按照文件权限进行判断
    • -r (有读的权限)
    • -w (有写的权限)
    • -x(有执行的权限)
  • 按照文件类型进行判断
    • -f(文件存在并且是一个常规文件)
    • -e(文件存在)
    • -d(文件存在并是一个目录)

流程控制

if判断

1
2
3
4
if [ 条件判断式 ]
then 
	代码
fi
1
2
3
4
5
6
7
if [ 条件判断式 ]
then
	代码
elif [ 条件判断式 ]
then
	代码
fi

case语句

1
2
3
4
5
6
7
8
9
10
11
case $变量名 in
"值1")
如果变量的值等于值1,则执行程序1
;;
"值2")
如果变量的值等于值2,则执行程序2
;;
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac

for循环

1
2
3
4
for 变量 in 值1 值2 值3...
do
代码
done
1
2
3
4
for ((初始值:循环控制条件:变量变化))
do
代码
done

while循环

1
2
3
4
while [ 条件判断式 ]
do
代码
done

read读取控制台输入

基本语法

1
read [选项] 参数

选项

  • -p指定读取值时的提示符
  • -t指定读取值时等待的时间(s)
  • 参数:指定变量名

系统函数

  1. basename [pathname] [suffix]
    返回完整路径最后/的部分,常用于获取文件名,suffix为后缀,如果指定了会把结果中的suffix去掉
  2. dirname [pathname]
    返回完整路径最后/之前的部分,常用于返回路径部分

自定义函数

基本语法

1
2
3
4
5
[ function ] funname[()]
{
	Action;
	[return int;]
}

调用的时候 funname [值]


本文参考

  1. HZ_Samuel
  2. Stephen_Tao
本文由作者按照 CC BY 4.0 进行授权