一、文件权限管理

文件所有者和属组属性操作
设置文件的所有者 chown

chown 命令可以修改文件的属性,也可以修改文件属组

格式:

chown [option] [user]:[group] filename 

用法说明:

  • USER 只修改所有者
  • USER:GROUP 同时修改所有者和属组
  • :GROUP 只修改属组,冒号也可用 . 替换
  • -R: 递归
  • --reference=RFILE 参考指定的的属性,来修改

示例:

[21:46:59 root@centos82[ data]#chown -R centos82:centos82 magedu
[21:47:25 root@centos82[ data]#ll
total 28
-rw-r--r--  1 root     root        65 Aug  3 15:29 hex.sh
drwxrwxrwx. 2 centos82 centos82    22 Aug  2 19:10 magedu
设置文件的属组信息 chgrp

chgrp 命令可以只修改文件的属组

格式:

chgrp [option] group filename
  • -R 递归

示例:

[21:47:28 root@centos82[ data]#chgrp -R root magedu
[21:51:50 root@centos82[ data]#ll
total 28
-rw-r--r--  1 root     root    65 Aug  3 15:29 hex.sh
drwxrwxrwx. 2 centos82 root    22 Aug  2 19:10 magedu
文件权限

文件权限说明:

文件权限主要针对三类对象:

  • owner 属主 :u
  • group 属组 :g
  • othoe 其他 :o

每个文件针对每类访问者定义了三中权限

  • 只读 r : readable
    • 可使用文件查看类工具获取其内容
  • 只写 w : writable
    • 可修改其内容
  • 只执行 x : excutable
    • 可以把此文件作为一个进程

对目录的权限:

  • r
    • 可以使用ls查看此目录中文件列表
  • w
    • 可在此目录中创建文件,也可以删除此目录中的文件
  • x
    • 可以使用ls -l 查看此目录中文件元数据(需要配合 r)
    • 可以 cd 进入此目录
  • X
    • 只给目录 x 权限,不给无执行权限的文件x权限

数学法的权限表示

Linux基础命令(二)_第1张图片

权限项 文件类型 执行 执行 执行
字符表示 (r) (w) (x) (r) (w) x) (r) (w) (x)
数字表示 4 2 1 4 2 1 4 2 1
修改文件权限

格式:

chmod [OPTION]... OCTAL-MODE FILE...
chmod [OPTION]... MODE[,MODE]... FILE...
#参考RFILE文件的权限,将FILE的修改为同RFILE
chmod [OPTION]... --reference=RFILE FILE...

说明:

  • -R: 递归修改权限
  • MODE:
    • 修改一类用户的所有权限 u= g= o= ug= a= u=,g=
    • 修改一类用户某位或某些位权限 u+ u- g+ g- o+ o- a+ a- + -

示例:

[21:51:52 root@centos82[ data]#ll hex.sh 
-rw-r--r-- 1 root root 65 Aug  3 15:29 hex.sh
[22:20:49 root@centos82[ data]#chmod o+x hex.sh 
[22:21:27 root@centos82[ data]#ll hex.sh 
-rw-r--r-x 1 root root 65 Aug  3 15:29 hex.sh
[22:21:31 root@centos82[ data]#chmod 756 hex.sh 
[22:21:49 root@centos82[ data]#ll hex.sh 
-rwxr-xrw- 1 root root 65 Aug  3 15:29 hex.sh
新建文件和目录的默认权限

umask 的值可以用来保留在创建文件权限

实现方式:

  • 非特权用户umask默认是 002
  • root的umask 默认是 022

  • 新建文件的默认权限: 666-umask,如果所得结果某位存在执行(奇数)权限,则将其权限+1,偶 数不变
  • 新建目录的默认权限: 777-umask

查看umask

[22:21:53 root@centos82[ data]#umask
0022

修改umask

[22:57:58 root@centos82[ data]#umask
0002
[22:58:00 root@centos82[ data]#umask 022
[22:58:15 root@centos82[ data]#umask 
0022

永久保存 umask

  • 全局设置

    • /etc/bashrc
  • 用户设置

    • ~/.bashrc
Linux文件系统上的特殊权限
特殊权限 SUID

安全上下文

前提:进程有属主和属组;文件有属主和属组

  1. 任何一个可执行程序文件能不能启动为进程,取决发起者对程序文件是否拥有执行权限
  2. 启动为进程之后,其进程的属主为发起者,进程的属组为发起者所属的组
  3. 进程访问文件时的权限,取决于进程的发起者
    • (a) 进程的发起者,同文件的属主:则应用文件属主权限
    • (b) 进程的发起者,属于文件属组;则应用文件属组权限
    • (c) 应用文件“其它”权限

二进制的可执行文件上SUID权限功能:

  • 任何一个可执行程序文件能不能启动为进程:取决发起者对程序文件是否拥有执行权限
  • 启动为进程之后,其进程的属主为原程序文件的属主
  • SUID只对二进制可执行程序有效
  • SUID设置在目录上无意义

SUID权限设定

chmod u+s FILE...
chmod 6xxx FILE
chmod u-s FILE...

示例:

[22:58:19 root@centos82[ data]#chmod u+s hex.sh 
[23:06:05 root@centos82[ data]#ll hex.sh 
-rwsr-xrw- 1 root root 65 Aug  3 15:29 hex.sh
特殊权限 SGID

二进制的可执行文件上SGID权限功能:

  • 任何一个可执行程序文件能不能启动为进程:取决发起者对程序文件是否拥有执行权限
  • 启动为进程之后,其进程的属组为原程序文件的属组

SGID权限设定:

chmod g+s FILE...
chmod 2xxx FILE
chmod g-s FILE...

目录上的SGID权限功能:

默认情况下,用户创建文件时,其属组为此用户所属的主组,一旦某目录被设定了SGID,则对此目录有 写权限的用户在此目录中创建的文件所属的组为此目录的属组,通常用于创建一个协作目录

SGID权限设定:

chmod g+s DIR...
chmod 2xxx DIR
chmod g-s DIR...

示例

[23:06:10 root@centos82[ data]#chmod g+s hex.sh 
[23:22:12 root@centos82[ data]#ll hex.sh 
-rwsr-srw- 1 root root 65 Aug  3 15:29 hex.sh
特殊权限 Sticky 位

具有写权限的目录通常用户可以删除该目录中的任何文件,无论该文件的权限或拥有权 在目录设置Sticky 位,只有文件的所有者或root可以删除该文件

sticky 设置在文件上无意义

Sticky权限设定:

chmod o+t DIR...
chmod 1xxx DIR
chmod o-t DIR...

示例

[23:33:02 root@centos82[ data]#ll
total 4
-rwsr-srw-  1 root     root 65 Aug  3 15:29 hex.sh
drwxrwxrwx. 2 centos82 root 22 Aug  2 19:10 magedu
[23:33:05 root@centos82[ data]#chmod o+t magedu
[23:33:22 root@centos82[ data]#ll
total 4
-rwsr-srw-  1 root     root 65 Aug  3 15:29 hex.sh
drwxrwxrwt. 2 centos82 root 22 Aug  2 19:10 magedu

权限位映射

  • SUID: user,占据属主的执行权限位
    • s:属主拥有x权限
    • S:属主没有x权限
  • SGID: group,占据属组的执行权限位
    • s: group拥有x权限
    • S:group没有x权限
  • Sticky: other,占据other的执行权限位
    • t:other拥有x权限
    • T:other没有x权限
设定文件的特殊属性

设置文件的特殊属性,可以访问root 用户误操作删除或修改文件

  • 不能删除,改名,更改

    • chattr +i
  • 只能追加内容

    • chattr +a
  • 显示特定属性

    • lsattr

示例

[23:33:23 root@centos82[ data]#lsattr hex.sh 
-------------------- hex.sh
[23:38:23 root@centos82[ data]#chattr +i hex.sh 
[23:38:31 root@centos82[ data]#lsattr hex.sh 
----i--------------- hex.sh
[23:38:38 root@centos82[ data]#rm -rf hex.sh 
rm: cannot remove 'hex.sh': Operation not permitted
访问控制列表
ACL 权限功能

ACL:Access Control List,实现灵活的权限管理

除了文件的所有者,所属组和其它人,可以对更多的用户设置权限

CentOS7 默认创建的xfs和ext4文件系统具有ACL功能

CentOS7 之前版本,默认手工创建的ext4文件系统无ACL功能,需手动增加

tune2fs –o acl /dev/sdb1
mount –o acl /dev/sdb1 /mnt/test

ACL生效顺序:

  • 所有者,自定义用户,所属组|自定义组,其他人
ACL 相关命令
  • setfacl 可以设置ACL权限
  • getfacl 可查看设置的ACL权限

添加用户

  • setfacl -m u:[user]:[rwx] filename|dir

添加组

  • setfacl -m g:[group]:[rwx] filename|dir

删除某个用户ACL权限

  • setfacl -x u:[user] filename|dir

删除某个组ACL权限

  • setfacl -x g:[group] filename|dir

清除所有ACL权限

  • setfacl -b filename|dir

查看ACL权限

  • getfacl filename|dir

示例:

[00:02:02 root@centos82[ data]#setfacl -m u:centos82:rw hex.sh 
[00:02:31 root@centos82[ data]#getfacl hex.sh 
# file: hex.sh
# owner: root
# group: root
# flags: ss-
user::rwx
user:centos82:rw-
group::r-x
mask::rwx
other::rw-

[00:02:44 root@centos82[ data]#setfacl -x u:centos82 hex.sh 
[00:03:06 root@centos82[ data]#getfacl hex.sh 
# file: hex.sh
# owner: root
# group: root
# flags: ss-
user::rwx
group::r-x
mask::r-x
other::rw-
mask 权限
  • mask只影响除所有者和other的之外的人和组的最大权限
  • mask需要与用户的权限进行逻辑与运算后,才能变成有限的权限(Effective Permission)
  • 用户或组的设置必须存在于mask权限设定范围内才会生效

格式

setfacl -m mask::[rwx] filename # 设置mask
setfacl -x mask filename        # 删除mask

示例

[00:07:08 root@centos82[ data]#setfacl -m mask::rw hex.sh 
[00:07:37 root@centos82[ data]#getfacl hex.sh 
# file: hex.sh
# owner: root
# group: root
# flags: ss-
user::rwx
group::r-x          #effective:r--
mask::rw-
other::rw-
[00:08:11 root@centos82[ data]#setfacl -x mask hex.sh 
[00:08:28 root@centos82[ data]#getfacl hex.sh 
# file: hex.sh
# owner: root
# group: root
# flags: ss-
user::rwx
group::r-x
other::rw-
备份和还原ACL

主要的文件操作命令cp和mv都支持ACL,只是cp命令需要加上-p 参数。但是tar等常见的备份工具是不 会保留目录和文件的ACL信息

#备份ACL
getfacl -R /tmp/dir > acl.txt
#消除ACL权限
setfacl -R -b /tmp/dir
#还原ACL权限
setfacl -R --set-file=acl.txt /tmp/dir
#还原ACL权限
setfacl --restore acl.txt
#查看ACL权限
getfacl -R /tmp/dir

示例

[00:08:34 root@centos82[ data]#setfacl -m mask::rw hex.sh 
[00:12:18 root@centos82[ data]#getfacl hex.sh 
# file: hex.sh
# owner: root
# group: root
# flags: ss-
user::rwx
group::r-x          #effective:r--
mask::rw-
other::rw-

[00:12:29 root@centos82[ data]#getfacl -R hex.sh > hex.txt
[00:13:05 root@centos82[ data]#cat hex.txt 
# file: hex.sh
# owner: root
# group: root
# flags: ss-
user::rwx
group::r-x  #effective:r--
mask::rw-
other::rw-
[00:13:12 root@centos82[ data]#setfacl -R -b hex.sh 
[00:14:18 root@centos82[ data]#getfacl hex.sh 
# file: hex.sh
# owner: root
# group: root
# flags: ss-
user::rwx
group::r--
other::rw-

[00:14:26 root@centos82[ data]#setfacl -R --set-file=hex.txt hex.sh
[00:15:10 root@centos82[ data]#getfacl hex.sh
# file: hex.sh
# owner: root
# group: root
# flags: ss-
user::rwx
group::r-x          #effective:r--
mask::rw-
other::rw-

###二、文本处理工具和正则表达式

文本编辑工具 Vim

文本编辑种类:

  • 全屏编辑器:nano(字符工具), gedit(图形化工具),vi,vim
    • vi
    • Visual editor,文本编辑器,是Linux 必备工具之一,功能强大,学习曲线较陡峭,学习难度大
    • vim
    • VIsual editor iMproved ,和vi 使用方法一致,但功能更为强大,不是必备软件
    • 官网:www.vim.org
    • 其他相关编辑器:gvim 一个Vim编辑器的图形版本
  • 行编辑器:sed

Vim

vi-vim-cheat-sheet-sch

Vim命令格式

vim [option] filename
  • +# 打开文件后,让光标处于第#行的行首,+默认行尾
  • +/PATTERN 让光标处于第一个被PATTERN匹配到的行行首
  • -b file 二进制方式打开文件
  • -d file1 file2… 比较多个文件,相当于 vimdiff
  • -m file 只读打开文件
  • -e file 直接进入ex模式,相当于执行ex file

说明:

  • 如果该文件存在,文件被打开并显示内容
  • 如果该文件不存在,当编辑后第一次存盘时创建它
三种主要模式和转换

三种常见模式

  • 命令或普通(Normal)模式:默认模式,可以实现移动光标,剪切/粘贴文本
  • 插入(Insert)或编辑模式:用于修改文本
  • 扩展命令(extended command )或命令(末)行模式:保存,退出等

模式转换

vim

  • 命令模式 --> 插入模式
    • i insert, 在光标所在处输入
    • I 在当前光标所在行的行首输入
    • a append, 在光标所在处后面输入
    • A 在当前光标所在行的行尾输入
    • o 在当前光标所在行的下方打开一个新行
    • O 在当前光标所在行的上方打开一个新行
  • 插入模式 --- ESC-----> 命令模式
  • 命令模式 ---- : ----> 扩展命令模式
  • 扩展命令模式 ----ESC,enter----> 命令模式
扩展命令模式
  • 按“:”进入Ex模式 ,创建一个命令提示符: 处于底部的屏幕左侧

扩展命令模式基本命令

w 写(存)磁盘文件
wq 写入并退出
x 写入并退出
X   加密
q 退出
q! 强制退出,不存盘退出,即使更改都将丢失
r     filename 读文件内容到当前文件中
w   filename 将当前文件内容写入另一个文件
!command 执行命令
r!command 读入命令的输出
地址定界

格式:

:start_pos,end_pos cmd 

参数:

**具体第#行,例如2表示第2行**
#,# 从左侧#表示起始行,到右侧#表示结尾行
#,+# 从左侧#表示的起始行,加上右侧#表示的行数,范例:2,+3 表示2到5行
.   当前行
$ 最后一行
.,$-1 当前行到倒数第二行
% 全文, 相当于1,$
/pattern/   从当前行向下查找,直到匹配pattern的第一行,即:正则表达式
/pat1/,/pat2/ 从第一次被pat1模式匹配到的行开始,一直到第一次被pat2匹配到的行结束
#,/pat/     从指定行开始,一直找到第一个匹配patttern的行结束
/pat/,$     向下找到第一个匹配patttern的行到整个文件的结尾的所有行

地址定界后跟一个编辑命令

d       删除
y 复制
w file: 将范围内的行另存至指定文件中
r file:在指定位置插入指定文件中的所有内容
查找并替换

格式

:s/要查找的内容/替换为的内容/修饰符  # 光标在首位
  • 要查找的内容:可使用正则表达式模式
  • 替换为的内容:不能使用模式,但可以使用\1, \2, ...等后向引用符号;还可以使用“&”引用前面查找时查 找到的整个内容

  • 修饰符:
    • i 忽略大小写
    • g 全局替换,默认情况下,每一行只替换第一次出现
    • gc 全局替换,每次替换前询问

说明:查找替换中的分隔符/可替换为其它字符,如:#,@

设置Vim的一些常用命令

配置文件:永久有效

全局:/etc/vimrc

个人:~/.vimrc

扩展命令模式:当前vim进程有效

  • 行号
    • 显示:set number,简写 set nu
    • 取消显示:set nonumber, 简写 set nonu
  • 忽略字符的大小写
    • 启用:set ignorecase,简写 set ic
    • 不忽略:set noic
  • 自动缩进
    • 启用:set autoindent,简写 set ai
    • 禁用:set noai
  • 复制保留格式
    • 启用:set paste
    • 禁用:set nopaste
  • 显示tab和换行符 ^| 和 $ 显示
    • 启用:set list
    • 禁用:set nolist
  • 高亮搜索
    • 启用:set hlsearch
    • 禁用:set nohlsearch
  • 语法高亮
    • 启用:syntax on
    • 禁用:syntax of
  • 文件格式
    • 启用windows格式:set fileformat=dos
    • 启用unix格式:set fileformat=unix
    • 简写 set ff=dos|unix
  • 设置文本宽度
    • set textwidth=65 (vim only)
    • set wrapmargin=15
  • 设置光标所在行的标识符
    • 启用:set cursorline,简写 set cul
    • 禁用:set nocursorline
  • 加密
    • 启用: set key=password
    • 禁用: set key=
  • 了解更多
    • set 帮助
    • :help option-list
    • :set or :set all
命令模式

命令模式功能强大,只是按键时,看不到输入,所以需要大量的记忆才能更好的使用。

退出Vim

  • ZZ 保存退出
  • ZQ 不保存退出

光标跳转

  • 字符间跳转:
    • h: 左 L: 右 j: 下 k: 上
    • #COMMAND:跳转由#指定的个数的字符
  • 单词间跳转:
    • w:下一个单词的词首
    • e:当前或下一单词的词尾
    • b:当前或前一个单词的词首
    • #COMMAND:由#指定一次跳转的单词数
  • 当前页跳转:
    • H:页首 M:页中间行 L:页底
    • zt:将光标所在当前行移到屏幕顶端
    • zz:将光标所在当前行移到屏幕中间
    • zb:将光标所在当前行移到屏幕底端
  • 行首行尾跳转:
    • ^ 跳转至行首的第一个非空白字符
    • 0 跳转至行首
    • $ 跳转至行尾
  • 行间移动:
    • #G 或者扩展命令模式下:# 跳转至由第#行
    • G 最后一行
    • 1G, gg 第一行
  • 句间移动:

    • ) 下一句
    • ( 上一句
  • 段落间移动:
    • } 下一段
    • { 上一段

命令模式翻屏操作

  • Ctrl+f 向文件尾部翻一屏
  • Ctrl+b 向文件首部翻一屏
  • Ctrl+d 向文件尾部翻半屏
  • Ctrl+u 向文件首部翻半屏

字符编辑

  • x 删除光标处的字符
  • #x 删除光标处起始的#个字符
  • xp 交换光标所在处的字符及其后面字符的位置
  • ~ 转换大小写
  • J 删除当前行后的换行符

替换命令

  • r 替换光标所在处的字符
  • R 切换成REPLACE模式,按ESC回到命令模式

删除命令

  • d 删除命令,可结合光标跳转字符,实现范围删除
  • d$ 删除到行尾
  • d^ 删除到非空行首
  • d0 删除到行首
  • dw de db #COMMAND
  • dd:删除光标所在的行
  • #dd 多行删除
  • D:从当前光标位置一直删除到行尾,等同于d$

复制命令

  • y 复制,行为相似于d命令
  • y$ y0 y^ ye yw yb #COMMAND
  • yy:复制行
  • #yy 复制多行
  • Y:复制整行

粘贴命令

  • p 缓冲区存的如果为整行,则粘贴当前光标所在行的下方;否则,则粘贴至当前光标所在处的后面
  • P 缓冲区存的如果为整行,则粘贴当前光标所在行的上方;否则,则粘贴至当前光标所在处的前面

改变命令

  • c: 删除后切换成插入模式
  • c$ c^ c0 cb ce cw #COMMAND
  • cc:删除当前行并输入新内容,相当于S
  • #cc
  • C:删除当前光标到行尾,并切换成插入模式,相当于c$

查找命令

  • /PATTERN:从当前光标所在处向文件尾部查找
  • ?PATTERN:从当前光标所在处向文件首部查找
  • n:与命令同方向
  • N:与命令反方向

撤销更改

  • u 撤销最近的更改
  • #u 撤销之前多次更改
  • U 撤消光标落在这行后所有此行的更改
  • Ctrl - r 重做最后的“撤消”更改
  • . 重复前一个操作
  • #. 重复前一个操作#次
可视化模式

允许选择的文本块

  • v 面向字符
  • V 面向整行
  • ctrl-v 面向块

可视化键可用于与移动键结合使用

  • w ) } 箭头

突出显示的文字可被删除,复制,变更,过滤,搜索,替换等

范例:在文件行首插入#

输入ctrl+v 进入可视化模式
输入 G 跳到最后1行,选中第一行
输入 I 切换至插入模式
输入 #
按 ESC 键
多文件模式
vim FILE1 FILE2 FILE3 ...
:next 下一个
:prev 前一个
:first 第一个
:last 最后一个
:wall 保存所有
:qall 不保存退出所有
:wqall保存退出所有
多窗口模式

多文件分割

  • vim -o|-O FILE1 FILE2 ...
  • -o: 水平或上下分割
  • -O: 垂直或左右分割(vim only)
  • 在窗口间切换:Ctrl+w, Arrow

单文件窗口分割

  • Ctrl+w,s:split, 水平分割
  • Ctrl+w,v:vertical, 垂直分割
  • ctrl+w,q:取消相邻窗口
  • ctrl+w,o:取消全部窗口
  • :wqall 退出
Vim寄存器

有26个命名寄存器和1个无命名寄存器,常存放不同的剪贴版内容,可以不同会话间共享 寄存器名称a,b,…,z,

格式:

  • “寄存器 放在数字和命令之间

范例:

  • 3"tyy 表示复制3行到t寄存器中
  • "tp 表示将t寄存器内容粘贴
  • 未指定,将使用无命名寄存器

有10个数字寄存器,用0,1,…,9表示,0存放最近复制内容,1存放最近删除内容。当新的文本变更 和删除时,1转存到2,2转存到3,以此类推。数字寄存器不能在不同会话间共享

编辑二进制文件
#以二进制方式打开文件
vim -b binaryfile
#扩展命令模式下,利用xxd命令转换为可读的十六进制
:%!xxd
#插入模式下,编辑二进制文件
#扩展命令模式下,利用xxd命令转换回二进制
:%!xxd -r
#保存退出
帮助
:help
:help topic
Use :q to exit help
vimtutor

文本常见处理工具

文件内容查看命令
cat 查看文本内容

格式

cat [OPTION]... [FILE]...

常见选项

  • -E:显示行结束符$
  • -A:显示所有控制符
  • -n:对显示出的每一行进行编号
  • -b:非空行编号
  • -s:压缩连续的空行成一行
  • tac 逆向显示文本内容
  • nl 显示行号,相当于cat -b
  • rev 将同一行的内容逆向显示
[01:41:22 root@centos82[ data]#cat -b hex.txt 
     1  #`` file: hex.aak
     2  mask::rw-
     3  other::rw-
查看非文本文件内容

hexdump 文本内容以16进制显示

[01:41:31 root@centos82[ data]#hexdump hex.txt
0000000 6023 2060 6966 656c 203a 6568 2e78 6161
0000010 0a6b 616d 6b73 3a3a 7772 0a2d 746f 6568
0000020 3a72 723a 2d77 0a0a                    
0000028

od 文本内容以八进制显示

od 即 dump files in octal and other formats

[01:43:07 root@centos82[ data]#od hex.txt 
0000000 060043 020140 064546 062554 020072 062550 027170 060541
0000020 005153 060555 065563 035072 073562 005055 072157 062550
0000040 035162 071072 026567 005012
0000050

xxd 文本内容以二进制显示

[01:44:24 root@centos82[ data]#xxd hex.txt
00000000: 2360 6020 6669 6c65 3a20 6865 782e 6161  #`` file: hex.aa
00000010: 6b0a 6d61 736b 3a3a 7277 2d0a 6f74 6865  k.mask::rw-.othe
00000020: 723a 3a72 772d 0a0a                      r::rw-..
分页查看文本内容

more 可以实现分页查看文件,可以配合管道实现输出信息的分页

格式

more [option] file

选项:

  • -d : 显示翻页及退出提示
[01:50:02 root@centos82[ data]#more -d hex.txt 
/etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
polkitd:x:998:996:User for polkitd:/:/sbin/nologin
sssd:x:997:994:User for sssd:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
rngd:x:996:993:Random Number Generator Daemon:/var/lib/rngd:/sbin/nologin
centos82:x:1000:1000:centos82:/home/centos82:/bin/bash
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
hu:x:1002:1000::/home/hu:/bin/bash
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
--More--(17%)[Press space to continue, 'q' to quit.]
#**按回车键继续查看,按q退出**

less 可以实现分页查看文件或 STDIN 输出

查看时有用的命令包括:

  • /文本 搜索 文本
  • n/N 跳到下一个 或 上一个匹配

less 命令是man命令使用的分页器

[01:52:50 root@centos82[ data]#less hex.txt 
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
hu:x:1002:1000::/home/hu:/bin/bash
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
:4
#**按回车确定,按q退出**
显示文本前后行内容

head 可以显示文件或标准输入的前面行

格式:

  • head [option] file

选项:

  • -c # 指定获取前#字节
  • -n # 指定获取前#行
  • -# 同上
[01:57:04 root@centos82[ data]#head -n 3 hex.txt 
/etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
[01:57:15 root@centos82[ data]#cat /dev/urandom | tr -dc [[:alnum:]] | head -c12
Ek]lIwph0oQI[01:58:57 root@centos82[ data]#

tail 查看文件或标准输入的倒数行

格式

  • tail [option] file

选项:

  • c # 指定获取后#字节
  • -n # 指定获取后#行
  • -# 同上
  • -f 跟踪显示文件fd新追加的内容,常用日志监控,相当于 --follow=descriptor,当文件删除再新建同名文 件,将无法继续跟踪文件
  • -F 跟踪文件名,相当于--follow=name --retry,当文件删除再新建同名文件,将可以继续跟踪文件
  • tailf 类似tail –f,当文件不增长时并不访问文件
[02:04:24 root@centos82[ data]#tail -n 3 /var/log/dnf.log
2020-08-03T17:41:23Z DEBUG Making cache files for all metadata files.
2020-08-03T17:41:24Z INFO Metadata cache refreshed recently.
2020-08-03T17:41:24Z DDEBUG Cleaning up.
按列抽取文本

cut 可以提取文本文件或STDIN数据的指定列

格式

  • cut [option] file

选项:

  • -d DELIMITER: 指明分隔符,默认tab
  • -f FILEDS:
    • #: 第#个字段,例如:3
    • #,#[,#]:离散的多个字段,例如:1,3,6
    • #-#:连续的多个字段, 例如:1-6
    • 混合使用:1-3,7
  • -c 按字符切割
  • --output-delimiter=STRING指定输出分隔符
[02:10:10 root@centos82[ data]#df
Filesystem     1K-blocks    Used Available Use% Mounted on
devtmpfs          389604       0    389604   0% /dev
tmpfs             405260       0    405260   0% /dev/shm
tmpfs             405260    5760    399500   2% /run
tmpfs             405260       0    405260   0% /sys/fs/cgroup
/dev/sda2      104806400 2393228 102413172   3% /
/dev/sda5       52403200  398448  52004752   1% /data
/dev/sda1         999320  175796    754712  19% /boot
tmpfs              81052       0     81052   0% /run/user/0
tmpfs              81052       0     81052   0% /run/user/1000
[02:10:21 root@centos82[ data]#df | tr -s ' ' '-' | cut -d'-' -f5 | tail -n 9 
0%
0%
2%
0%
3%
1%
19%
0%
0%
合并多个文件

paste 合并多个文件同行号的列到同一行

格式

  • paste [option] file1 file2 

选项:

  • -d 分隔符:指定分隔符,默认用TAB
  • -s : 所有行合成一行显示
[02:14:51 root@centos82[ data]#paste a.txt b.txt 
1   a
2   b
3   c 
4   d 
5   e 
6   f 
7   g 
8   h 
9   i 
10  j 
11  k 
分析文本的工具

文本数据统计:wc

整理文本:sort

比较文件:diff和patch

收集文本统计数据

wc 命令可用于统计文件的行总数、单词总数、字节总数和字符总数 可以对文件或STDIN中的数据统计

选项:

  • -l 只计数行数
  • -w 只计数单词总数
  • -c 只计数字节总数
  • -m 只计数字符总数
  • -L 显示文件中最长行的长度
[02:16:23 root@centos82[ data]#wc -L a.txt 
2 a.txt
[02:18:31 root@centos82[ data]#wc a.txt 
   20   20    51 a.txt
**行数 单词数 字节数**
文本排序 sort

把整理过的文本显示在STDOUT,不改变原始文件

格式:

  • sort [option] file

选项:

  • -r 执行反方向(由上至下)整理
  • -R 随机排序
  • -n 执行按数字大小整理
  • -f 选项忽略(fold)字符串中的字符大小写
  • -u 选项(独特,unique)删除输出中的重复行
  • -t c 选项使用c做为字段界定符
  • -k # 选项按照使用c字符分隔的 # 列来整理能够使用多次
[02:41:11 root@centos82[ data]#cat b.txt 
a
b
c 
a
e 
f g 
h 

d
i 
j 

l 
m 

n

m
n 
o 
p
n
[02:41:40 root@centos82[ data]#sort -u b.txt 

a
b
c 
d
e 
f g 
h 
i 
j 
l 
m
m 
n
n 
o 
p
去重 uniq

uniq命令从输入中删除前后相接的重复的行

格式:

  • uniq [option] file

选项:

  • -c: 显示每行重复出现的次数
  • -d: 仅显示重复过的行
  • -u: 仅显示不曾重复的行

uniq 常和 sort 命令一起配合使用

[02:47:49 root@centos82[ data]#sort b.txt
a
a
b
c
d
e
f g 
h
i
j
l
m
m
n
n
n
o
p
[02:47:58 root@centos82[ data]#sort b.txt |uniq -c
      2 a
      1 b
      1 c
      1 d
      1 e
      1 f g 
      1 h
      1 i
      1 j
      1 l
      2 m
      3 n
      1 o
      1 p
比较文件

diff 比较两个文件之间的区别

[14:14:38 root@centos82[ data]#diff a.txt b.txt 
1,2d0
< 1
< 2
3a2
> b
5c4,6
< 3
---
> 1
> 4
> 6

[14:14:28 root@centos82[ data]#diff -u a.txt b.txt 
--- a.txt   2020-08-04 02:52:19.709256275 +0800
+++ b.txt   2020-08-04 02:52:51.339257429 +0800
@@ -1,5 +1,6 @@
-1
-2
 a
+b
 c
-3
+1
+4
+6

复制对文件改变patch

diff 命令的输出被保存在一种叫做“补丁”的文件中

  • 使用 -u 选项来输出“统一的(unified)”diff格式文件,最适用于补丁文件

patch 复制在其它文件中进行的改变(要谨慎使用)

  • 适用 -b 选项来自动备份改变了的文件

文本处理三剑客

  • grep 命令主要对文本的(正则表达式)行基于模式进行过滤
  • sed:stream editor,文本编辑工具
  • awk:Linux上的实现gawk,文本报告生成器
grep

grep: Global search REgular expression and Print out the line

作用:文本搜索工具,根据用户指定的“模式”对目标文本逐行进行匹配检查;打印匹配到的行

模式:由正则表达式字符及文本字符所编写的过滤条件

格式:

grep [OPTIONS] PATTERN [FILE...]

常见选项:

  • --color=auto 对匹配到的文本着色显示
  • -m # 匹配#次后停止
  • -v 显示不被pattern匹配到的行
  • -i 忽略字符大小写
  • -n 显示匹配的行号
  • -c 统计匹配的行数
  • -o 仅显示匹配到的字符串
  • -q 静默模式,不输出任何信息
  • -A # after, 后#行
  • -B # before, 前#行
  • -C # context, 前后各#行
  • -e 实现多个选项间的逻辑or关系,如:grep –e ‘cat ’ -e ‘dog’ file -
  • w 匹配整个单词
  • -E 使用ERE,相当于egrep
  • -F 相当于fgrep,不支持正则表达式
  • -f file 根据模式文件处理
  • -r 递归目录,但不处理软链接
  • -R 递归目录,但处理软链接
[09:21:01 root@centos80 test]#cat /etc/passwd > pass.txt
[09:22:55 root@centos80 test]#grep -no 'bin' pass.txt 
1:bin
2:bin
2:bin
2:bin
2:bin
3:bin
3:bin
[09:23:17 root@centos80 test]#grep -oi 'SSH' pass.txt 
ssh
SSH
ssh
[09:27:49 root@centos80 test]#grep -vin 'SSH' pass.txt 
1:root:x:0:0:root:/root:/bin/bash
2:bin:x:1:1:bin:/bin:/sbin/nologin
3:daemon:x:2:2:daemon:/sbin:/sbin/nologin
4:adm:x:3:4:adm:/var/adm:/sbin/nologin
5:lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[09:44:21 root@centos80 test]#grep -wn 'r..t' pass.txt 
1:root:x:0:0:root:/root:/bin/bash
10:operator:x:11:0:operator:/root:/sbin/nologin
[10:10:19 root@centos80 test]#grep -E 'root|bash' pass.txt 
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
centos80:x:1000:1000:centos80:/home/centos80:/bin/bash

示例:取 IP

[09:36:32 root@centos80 test]#ss -nt | grep -Eo "1[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}:[0-9]{1,5}"
10.0.0.80:22
10.0.0.1:4254
10.0.0.80:22
10.0.0.1:3891
[09:40:27 root@centos80 test]#ss -nt | grep "^ESTAB" | tr -s ' ' '%' | cut -d'%' -f5 | sort -n
10.0.0.1:3891
10.0.0.1:4254

正则表达式

REGEXP : Regular Expressions , 由一类特殊字符及文本字符所编写的模式,其中有些字符(元字符)不表示字符字面意义,而表示控制或通配的功能,类似于增强版的通配符功能,但于通配符不同,通配符功能是用来处理文件名,而正则表达式是处理文本内容中字符

正则表达式分两类:

  • 基本正则表达式:BRE
  • 扩展正则表达式:ERE

正则表达式引擎:

  • 采用不同算法,检查处理正则表达式的软件模块,如:PCRE,

正则表达式的元字符分类:

  • 字符匹配,匹配次数,位置锚点,分组
基本正则表达式元字符
字符匹配
.   匹配任意单个字符
[]   匹配指定范围内的任意单个字符,示例:[wang]   [0-9]   [a-z]   [a-zA-Z]
[^] 匹配指定范围外的任意单个字符,示例:[^wang]
[:alnum:] 字母和数字
[:alpha:] 代表任何英文大小写字符,亦即 A-Z, a-z
[:lower:] 小写字母,示例:[[:lower:]],相当于[a-z]
[:upper:] 大写字母
[:blank:] 空白字符(空格和制表符)
[:space:] 水平和垂直的空白字符(比[:blank:]包含的范围广)
[:cntrl:] 不可打印的控制字符(退格、删除、警铃...)
[:digit:] 十进制数字
[:xdigit:]十六进制数字
[:graph:] 可打印的非空白字符
[:print:] 可打印字符
[:punct:] 标点符号

示例:

[10:58:19 root@centos80 test]#ls /etc | grep "re[[:alnum:]]."
bindresvport.blacklist
centos-release
centos-release-upstream
firewalld
libreport
os-release
prelink.conf.d
redhat-release
resolv.conf
system-release
system-release-cpe
yum.repos.d
匹配次数

用在要指定次数的字符后面,用于指定前面的字符要出现的次数

* 匹配前面的字符任意次,包括0次,贪婪模式:尽可能长的匹配
.* 任意长度的任意字符
\? 匹配其前面的字符0或1次,即:可有可无
\+ 匹配其前面的字符至少1次,即:肯定有
\{n\} 匹配前面的字符n次
\{m,n\} 匹配前面的字符至少m次,至多n次
\{,n\} 匹配前面的字符至多n次
\{n,\} 匹配前面的字符至少n次
[11:06:30 root@centos80 test]#echo /etc/ | grep "c\/\+"
/etc/
[11:07:20 root@centos80 test]#echo /etc/// | grep "c\/\+"
/etc///
[11:07:34 root@centos80 test]#echo /etc/// | grep "c\/\?"
/etc///
[11:07:55 root@centos80 test]#echo /etc/// | grep "c\/*"
/etc///
[11:08:22 root@centos80 test]#echo /etc/// | grep "c\/\{,5\}"
/etc///
位置锚点

位置锚点可以用于定位出现的位置

^ 行首锚定,用于模式的最左侧 
$ 行尾锚定,用于模式的最右侧 
^PATTERN$ 用于模式匹配整行 
^$ 空行 
^[[:space:]]*$ 空白行 
\< 或 \b 词首锚定,用于单词模式的左侧 
\> 或 \b 词尾锚定,用于单词模式的右侧 
\ 匹配整个单词

注意:单词是由字母,数字和下划线组成

示例

[11:12:28 root@centos80 test]#grep "^#" /etc/fstab 
#
# /etc/fstab
# Created by anaconda on Wed Aug  5 19:24:24 2020
[11:16:43 root@centos80 test]#cat /etc/fstab 

#
# /etc/fstab
# Created by anaconda on Wed Aug  5 19:24:24 2020
[11:18:06 root@centos80 test]#grep -v "^$" /etc/fstab 
#
# /etc/fstab
# Created by anaconda on Wed Aug  5 19:24:24 2020
[11:18:18 root@centos80 test]#grep "^[^$]" /etc/fstab 
#
# /etc/fstab
# Created by anaconda on Wed Aug  5 19:24:24 2020
[11:18:34 root@centos80 test]#grep "^[^$]" /etc/fstab | grep "20\>"
# Created by anaconda on Wed Aug  5 19:24:24 2020
# 删除空行,#字开头的行
[11:20:01 root@centos80 test]#grep -v "^$" /etc/fstab | grep -v "^#"
UUID=2d7c8adc-a563-48f6-bb2e-1abaf22ca2a3 /                       xfs     defaults        0 0
UUID=7ea05c8b-46eb-48f0-809a-a6f29cf5ba30 /boot                   ext4    defaults        1 2
UUID=98641b04-acbc-4a7b-b103-3d48eace0f96 /data                   xfs     defaults        0 0
UUID=7e99ba0b-050d-44bf-be1b-d0366beff897 swap                    swap    defaults        0 0
[11:29:21 root@centos80 test]#grep "^[^$]" /etc/fstab | grep "^[^#]"
UUID=2d7c8adc-a563-48f6-bb2e-1abaf22ca2a3 /                       xfs     defaults        0 0
UUID=7ea05c8b-46eb-48f0-809a-a6f29cf5ba30 /boot                   ext4    defaults        1 2
UUID=98641b04-acbc-4a7b-b103-3d48eace0f96 /data                   xfs     defaults        0 0
UUID=7e99ba0b-050d-44bf-be1b-d0366beff897 swap                    swap    defaults        0 0
分组

分组:() 将一个或多个字符捆绑在一起,当作一个整体处理,如:(root)+

分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名方式为: \1, \2, \3, ...

\1 表示从左侧起第一个左括号以及与之匹配右括号之间的模式所匹配到的字符

格式:

\(string1\(string2\)\)
\1 :string1\(string2\)
\2 :string2

后向引用:引用前面的分组括号中的模式所匹配字符,而非模式本身

示例:

[11:36:51 root@centos80 test]#grep "\(sbin\)" pass.txt 
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
或者 |

格式:

a\|b #a或b  
C\|cat #C或cat  
\(C\|c\)at #Cat或cat

示例:

[11:41:45 root@centos80 test]#grep "\(root\)\|\(sbin\)" pass.txt 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
扩展正则表达式

grep :-E 使用ERE,相当于egrep扩展表达式

字符匹配元字符
. 任意单个字符
[wang] 指定范围的字符
[^wang] 不在指定范围的字符
[:alnum:] 字母和数字
[:alpha:] 代表任何英文大小写字符,亦即 A-Z, a-z
[:lower:] 小写字母,示例:[[:lower:]],相当于[a-z]
[:upper:] 大写字母
[:blank:] 空白字符(空格和制表符)
[:space:] 水平和垂直的空白字符(比[:blank:]包含的范围广)
[:cntrl:] 不可打印的控制字符(退格、删除、警铃...)
[:digit:] 十进制数字
[:xdigit:]十六进制数字
[:graph:] 可打印的非空白字符
[:print:] 可打印字符
[:punct:] 标点符号
次数匹配
*   匹配前面字符任意次
? 0或1次
+ 1次或多次
{n} 匹配n次
{m,n} 至少m,至多n次
位置锚点
^ 行首
$ 行尾
\<, \b 语首
\>, \b 语
分组 ,或
() 分组
后向引用:\1, \2, ...
| 或者
a|b #a或b
C|cat #C或cat
(C|c)at #Cat或cat

三、shell 编程

编程基础

Linus:Talk is cheap, show me the code

翻译:废话少说,放码过来

程序组成
  • 程序:算法+数据结构
  • 数据:是程序的核心
  • 算法:处理数据的方式
  • 数据结构:数据在计算机中的类型和组织方式
程序编程风格
  • 过程式:以指令为中心,数据服务于指令,shell脚本程序提供了编程能力,解释执行
  • 对象式:以数据为中心,指令服务于数据,java,C#,python等
编程语言

计算机:运行二进制指令

编程语言:人与计算机之间交互的语言。分为两种:低级语言和高级语言

  • 低级编程语言:
    • 机器:二进制的0和1的序列,称为机器指令。与自然语言差异太大,难懂、难写
    • 汇编:用一些助记符号替代机器指令,称为汇编语言
    • 如:ADD A,B 将寄存器A的数与寄存器B的数相加得到的数放到寄存器A中 汇编语言写好的程序需要汇编程序转换成机器指令
    • 汇编语言稍微好理解,即机器指令对应的助记符,助记符更接近自然语言
  • 高级编程语言:
    • 编译:高级语言-->编译器-->机器代码文件-->执行,如:C,C++
    • 解释:高级语言-->执行-->解释器-->机器代码,如:shell,python,php,JavaScript,perl 编译和解释型语言
编程逻辑处理方式
  • 顺序执行
  • 选择执行
  • 循环执行

shell 脚本基础

shell脚本编程:是基于过程式、解释执行的语言

编程语言的基本结构:

  • 各种系统命令的组合
  • 数据存储:变量、数组
  • 表达式:a + b
  • 控制语句:if

shell脚本:包含一些命令或声明,并符合一定格式的文本文件

格式要求:首行shebang机制

#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl 
创建 shell 脚本过程
  • 第一步:使用文本编辑器来创建文本文件

    • 第一行必须包括shell声明序列:#!

    • 示例:
      #!/bin/bash 
      查看当前shell进程
      [11:42:15 root@centos80 test]#echo $SHELL
      /bin/bash
      查看系统支持shell类型
      [12:55:11 root@centos80 test]#cat /etc/shells
      /bin/sh
      /bin/bash
      /usr/bin/sh
      /usr/bin/bash
  • 第二步:加执行权限

    • 给予执行权限,在命令行上指定脚本的绝对或相对路径
  • 第三步:运行脚本

    • 直接运行解释器,将脚本作为解释器程序的参数运行
shell 脚本注释规范
  • 1、第一行一般为调用使用的语言
  • 2、程序名,避免更改文件名为无法找到正确的文件
  • 3、版本号
  • 4、更改后的时间
  • 5、作者相关信息
  • 6、该程序的作用,及注意事项
  • 7、最后是各版本的更新简要说明

测试第一个脚本

[13:03:00 root@centos80 test]#cat demo.sh 
#!/bin/bash
echo "Hello World!"
[13:03:16 root@centos80 test]#chmod u+x demo.sh 
[13:03:27 root@centos80 test]#sh demo.sh 
Hello World!
[13:03:35 root@centos80 test]#bash demo.sh 
Hello World!
[13:03:39 root@centos80 test]#./demo.sh 
Hello World!
[13:03:45 root@centos80 test]#/data/test/demo.sh 
Hello World!
[13:04:42 root@centos80 test]#cat demo.sh | bash
Hello World!
[13:05:02 root@centos80 test]#bash < ./demo.sh 
Hello World!
[13:05:26 root@centos80 test]#yum -y install httpd
[13:05:52 root@centos80 test]#systemctl start httpd
[13:06:27 root@centos80 test]#cp -a /data/test/
bash      demo.sh   pass.txt  
[13:06:27 root@centos80 test]#cp -a /data/test/demo.sh /var/www/html/
[13:07:05 root@centos80 test]#curl http://10.0.0.80/demo.sh
#!/bin/bash
echo "Hello World!"
shell 脚本测试
  • 只检测脚本中的语法错误,但无法检查出命令错误,但不真正执行脚本

    • bash -n demo.sh
  • 调试并执行脚本

    • bash -x demo.sh

脚本错误常见的有三种

  • 语法错误
    • 会导致后续命令不继续执行,可以使用bash -n检查错误,提示的出错行数不一定准确
  • 命令错误
    • 默认后续的命令还会继续执行,用bash -n无法检查,可以使用bash -x进行观察
  • 逻辑错误
    • 只能使用bash -x进行观察
变量

变量

变量表示命名的内存空间,将数据放在内存空间中,通过变量名引用,获取数据

变量类型

变量类型:

  • 内置变量,如:PS1,PATH,HISTSIZE
  • 用户自定义变量

不同的变量存放的数据不同,决定了以下

  1. 数据存储方式
  2. 参与的运算
  3. 表示的数据范围

变量数据类型:

  • 字符
  • 数值:整型、浮点型,bash 不支持浮点数
编程语言分类

静态和动态语言

  • 静态编译语言:使用变量前,先声明变量类型,之后类型不能改变,在编译时检查,如:java,c
  • 动态编译语言:不用事先声明,可随时改变类型,如:bash,Python

强类型和弱类型语言

  • 强类型语言:不同类型数据操作,必须经过强制转换才同一类型才能运算,如java , c# , python 如:以下python代码 print('magedu'+ 10) 提示出错,不会自动转换类型 print('magedu'+str(10)) 结果为magedu10,需要显示转换类型
  • 弱类型语言:语言的运行时会隐式做数据类型转换。无须指定类型,默认均为字符型;参与运算会 自动进行隐式类型转换;变量无须事先定义可直接调用 如:bash ,php,javascript
变量的命名法则
  • 不能使程序中的保留字:如:if, for
  • 只能使用数字、字母及下划线,且不能以数字开头,注意:不支持短横线 “ - ” 见名知义,用英文名字,并体现出实际作用
  • 统一命名规则:驼峰命名法, studentname,大驼峰StudentName 小驼峰studentName
  • 变量名大写
  • 局部变量小写
  • 函数名小写
变量定义和引用变量的生效范围等标准划分变量类型
  • 普通变量
    • 生效范围为当前shell进程;对当前shell之外的其它shell进程,包括当前shell的子shell 进程均无效
  • 环境变量
    • 生效范围为当前shell进程及其子进程
  • 本地变量
    • 生效范围为当前shell进程中某代码片断,通常指函数
普通变量

变量赋值

name="value"

value 可以是以下多种形式

直接字串:name='root'
变量引用:name="$USER"
命令引用:name=`COMMAND` 或者 name=$(COMMAND)

变量引用

$name
或者
${name}

弱引用和强引用

  • "$name " 弱引用,其中的变量引用会被替换为变量值
  • '$name ' 强引用,其中的变量引用不会被替换为变量值,而保持原字符串

显示已定义的所有变量

set

删除变量

unset name
环境变量

环境变量:

  • 可以使子进程(包括孙子进程)继承父进程的变量,但是无法让父进程使用子进程的变量
  • 一旦子进程修改从父进程继承的变量,将会新的值传递给孙子进程
  • 一般只在系统配置文件中使用,在脚本中较少使用

变量的声明和赋值

# 声明并赋值
export name=VALUE
declare -x name=VALUE

变量引用

$name
${name}

显示所有环境变量

env
printenv
export
declare -x

删除变量

unset name

bash 内建的环境变量

PATH
SHELL
USER
UID
HOME
PWD
SHLVL # shell 的嵌套层数。即深度
LANG
MAIL
HOSTNAME
HISTSIZE
_    # 下划线 表示前一命令的最后一个参数
只读变量

只读变量:只能声明定义,但后续不能修改和删除

声明只读变量

readonly name
declare -r name

查看只读变量

readonly [-p] name
declare -r

示例

[14:05:01 root@centos80 test]#readonly age=13
[14:07:23 root@centos80 test]#echo $age
13
[14:07:31 root@centos80 test]#unset age
bash: unset: age: cannot unset: readonly variable
位置变量

位置变量:在bash shell中内置的变量, 在脚本代码中调用通过命令行传递给脚本的参数

$1, $2, ... 对应第1个、第2个等参数,shift [n]换位置
$0 命令本身,包括路径
$* 传递给脚本的所有参数,全部参数合为一个字符串
$@ 传递给脚本的所有参数,每个参数为独立字符串
$# 传递给脚本的参数的个数
注意:$@ $* 只在被双引号包起来的时候才会有差异

清空所有位置变量

set --

示例

[14:13:29 root@centos80 test]#cat demo.sh 
#!/bin/bash
echo "Hello World!"
name=hu
readonly name
echo $name
echo "this is one: $1"
echo "this is two: $2"
echo "this is three: $3"
[14:13:40 root@centos80 test]#./demo.sh {a..z}
Hello World!
hu
this is one: a
this is two: b
this is three: c
Linux中变量#,#,@,0,0,1,2,2,*,$$,$?的含义
$# 是传给脚本的参数个数
$0 是脚本本身的名字
$1 是传递给该shell脚本的第一个参数
$2 是传递给该shell脚本的第二个参数
$@ 是传给脚本的所有参数的列表
$* 是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个
$$ 是脚本运行的当前进程ID号
$? 是显示最后命令的退出状态,0表示没有错误,其他表示有错误

**区别:@***

  • 相同点:都是引用所有参数
  • 不同点:只有在双引号中体现出来。
    • 假设在脚本运行时写了三个参数(分别存储在1 2 3)则" * " 等价于 “1 2 3"(传递了一个参数);而“3"(传递了一个参数);而“@" 等价于 "$1" "$2" "$3"(传递了三个参数)

示例

[08:34:03 root@centos80 test]#cat test.sh
#!/bin/bash
echo "a is $# , $0 , $1 , $2 , $@ , $* , $$ , $? "
echo "b is $# , $0 , $1 , $2 , $@ , $* , $$ , $? "
echo "c is $# , $0 , $1 , $2 , $@ , $* , $$ , $? "
echo "d is $# , $0 , $1 , $2 , $@ , $* , $$ , $? "
echo "e is $# , $0 , $1 , $2 , $@ , $* , $$ , $? "
echo "f is $# , $0 , $1 , $2 , $@ , $* , $$ , $? "

[08:34:07 root@centos80 test]#./test.sh {1..9}
a is 9 , ./test.sh , 1 , 2 , 1 2 3 4 5 6 7 8 9 , 1 2 3 4 5 6 7 8 9 , 2394172 , 0
b is 9 , ./test.sh , 1 , 2 , 1 2 3 4 5 6 7 8 9 , 1 2 3 4 5 6 7 8 9 , 2394172 , 0
c is 9 , ./test.sh , 1 , 2 , 1 2 3 4 5 6 7 8 9 , 1 2 3 4 5 6 7 8 9 , 2394172 , 0
d is 9 , ./test.sh , 1 , 2 , 1 2 3 4 5 6 7 8 9 , 1 2 3 4 5 6 7 8 9 , 2394172 , 0
e is 9 , ./test.sh , 1 , 2 , 1 2 3 4 5 6 7 8 9 , 1 2 3 4 5 6 7 8 9 , 2394172 , 0
f is 9 , ./test.sh , 1 , 2 , 1 2 3 4 5 6 7 8 9 , 1 2 3 4 5 6 7 8 9 , 2394172 , 0
退出状态码变量

在shell脚 本中$?表示程序执行的相应状态。

进程执行后,将使用变量 $? 保存状态码的相关数字,不同的值反应成功或失败,$?取值范例 0-255

$? 的值为0     # 代表成功
$? 的值是1-255 # 代表失败

示例

[08:46:52 root@centos80 test]#$?
-bash: 0: command not found
[08:53:13 root@centos80 test]#echo $?
127
[08:53:18 root@centos80 test]#ls
test01.sh  test02.sh  test.sh
[08:53:24 root@centos80 test]#echo $?
0

用户可以在脚本中使用以下命令自定义退出状态码

exit [n]

注意:

  • 脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字
  • 如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码
展开命令行

展开命令行顺序

把命令行分成单个命令词
展开别名
展开大括号的声明{}
展开波浪符声明 ~
命令替换$() 和 ``
再次把命令行分成命令词
展开文件通配*、?、[abc]等等
准备I/0重导向 <、>
运行命令

防止扩展

反斜线(\)会使随后的字符按原意解释
[09:09:16 root@centos80 test]#echo "hello \n world"
hello \n world
[09:09:23 root@centos80 test]#echo -e "hello \n world"
hello
 world

加引号来防止扩展

单引号(’’)防止所有扩展
双引号(”“)也可防止扩展,但是以下情况例外:$(美元符号)

变量扩展

`` : 反引号,命令替换
\:反斜线,禁止单个字符扩展
!:叹号,历史命令替换
脚本安全和set

set 命令:可以用来定制shell环境

$- 变量

  • h:hashall,打开选项后,Shell 会将命令所在的路径hash下来,避免每次都要查询。通过set +h将h选 项关闭
  • i:interactive-comments,包含这个选项说明当前的 shell 是一个交互式的 shell。所谓的交互式shell, 在脚本中,i选项是关闭的
  • m:monitor,打开监控模式,就可以通过Job control来控制进程的停止、继续,后台或者前台执行等
  • B:braceexpand,大括号扩展
  • H:history,H选项打开,可以展开历史列表中的命令,可以通过!感叹号来完成,例如“!!”返回上最近的 一个历史命令,“!n”返回第 n 个历史命令
[09:15:35 root@centos80 test]#hash
hits    command
   4    /usr/bin/chmod
   6    /usr/bin/vim
   1    /usr/bin/cat
   1    /usr/bin/ls
[09:15:59 root@centos80 test]#echo {1..10}
1 2 3 4 5 6 7 8 9 10
[09:16:45 root@centos80 test]#echo $-
himBHs
[09:16:58 root@centos80 test]#set +h
[09:17:06 root@centos80 test]#echo {1..10}
1 2 3 4 5 6 7 8 9 10
[09:17:14 root@centos80 test]#set +B
[09:17:25 root@centos80 test]#echo {1..10}
{1..10}
[09:17:36 root@centos80 test]#set +h
[09:17:51 root@centos80 test]#echo {1..10}
{1..10}
[09:17:57 root@centos80 test]#echo $-
imHs
[09:18:07 root@centos80 test]#set -B
[09:18:31 root@centos80 test]#echo {1..10}
1 2 3 4 5 6 7 8 9 10
[09:18:43 root@centos80 test]#hash
-bash: hash: hashing disabled

set 命令实现脚本安全

  • -u 在扩展一个没有设置的变量时,显示错误信息, 等同set -o nounset
  • -e 如果一个命令返回一个非0退出状态值(失败)就退出, 等同set -o errexit
  • -o option 显示,打开或者关闭选项
    • 显示选项:set -o
    • 打开选项:set -o 选项
    • 关闭选项:set +o 选项
  • -x 当执行命令时,打印命令及其参数,类似 bash -x
[09:18:57 root@centos80 test]#set -o
allexport       off
braceexpand     on
emacs           on
errexit         off
errtrace        off
functrace       off
hashall         off
histexpand      on
history         on
ignoreeof       off
interactive-comments    on
keyword         off
monitor         on
noclobber       off
noexec          off
noglob          off
nolog           off
notify          off
nounset         off
onecmd          off
physical        off
pipefail        off
posix           off
privileged      off
verbose         off
vi              off
xtrace          off
格式化输出 printf

格式

printf "指定的格式" "文本1" ”文本2“……

image-20200808092905485

替换符 功能
%s 字符串
%f 浮点格式
%b 相对应的参数中包含转义字符时,可以使用此替换符进行替换,对应的转义符会被转义
%c ASCII字符,即显示对应参数的第一个字符
%d , %i 十进制整数
%o 八进制
%u 不带正负号的十进制
%x 十六进制(a-f)
%X 十六进制(A-F)
%% 表示%本身

说明:%s 中的数字代表此替换符中的输出字符宽度,不足补空格,默认是右对齐,%-10s表示10个字 符宽,- 表示左对齐

常用转义符

转义符 功能
\a 警告符
\b 后退
\f 换页
\n 换行
\r 回车
\t 水平制表符
\v 垂直制表符
\ 表示\ 本身
[10:40:55 root@centos80 test]#printf "\n%s\t%s\t\n " 姓名 年龄 小明 18 男

姓名    年龄

小明    18

男
[10:42:38 root@centos80 test]#printf "%-10s%-10s\n" 姓名 年龄 小明 18 男
姓名    年龄
小明    18
男
算术运算符

shell 支持算术运算,let 和 declare 内置命令,(())复合命令和算术扩展。求值以固定宽度的整数进行,不检查溢出,尽管除以0被困并标记为错误。

bash中的算术运算

注意:bash 只支持整数,不支持小数

算数运算符 说明
+、- 加法(或正号)、减法(或负号)
*、/、% 乘法、除法、取模(取模,即取余数,示例:9%4=1)
** 幂运算
++、-- 自增和自减,可以放在变量的前面也可以放在变量的后面
!、&&、|| 逻辑非(取反)、逻辑与(and)、逻辑或(or)
<、<=、>、>= 比较符号(小于、小于等于、大于、大于等于)
==、!=、= 比较符号(相等、不相等;对于字符串,= 也可以表示相当于)
<<、>> 向左移位、向右移位
~、|、&、^ 按位取反、按位或、按位与、按位异或
=、+=、-=、*=、/=、%= 增强型赋值运算符,例如 a+=1 相当于 a=a+1,a-=1 相当于 a=a-1

乘法符号有些场景中需要转义

实现算术运算:

(1) let var=算术表达式
(2) ((var=算术表达式)) 和上面等价
(3) var=$[算术表达式]
(4) var=$((算术表达式))
(5) var=$(expr arg1 arg2 arg3 ...)
(6) declare –i var = 数值
(7) echo '算术表达式' | bc
[10:47:43 root@centos80 test]#a=1
[11:04:35 root@centos80 test]#b=2
[11:04:37 root@centos80 test]#let c=a+b
[11:04:48 root@centos80 test]#echo $c
3
[11:04:56 root@centos80 test]#echo $((a+b))
3
[11:05:39 root@centos80 test]#echo $[a+b]
3
[11:05:51 root@centos80 test]#echo $((a+=2))
3

内建的随机数生成器变量

$RANDOM  取值范围:0-32767
[10:42:46 root@centos80 test]#echo $RANDOM
11774
逻辑运算

true false

1 真
0 假

与:&:和0相与,结果为0,和1相与,结果保留原值

1 与 1 = 1
1 与 0 = 0
0 与 1 = 0
0 与 0 = 0

或:|:和1相或结果为1,和0相或,结果保留原值

1 或 1 = 1
1 或 0 = 1
0 或 1 = 1
0 或 0 = 0

非:!

! 1 = 0 ! true
! 0 = 1 ! false

异或 :^

异或的两个值,相同为假,不同为真。两个数字X,Y异或得到结果Z,Z再和任意两者之一X异或,将得 出另一个值Y

1 ^ 1 = 0
1 ^ 0 = 1
0 ^ 1 = 1
0 ^ 0 = 0
[11:07:45 root@centos80 test]#true
[11:11:40 root@centos80 test]#echo $?
0
[11:11:44 root@centos80 test]#false
[11:11:51 root@centos80 test]#echo $?
1

短路运算

  • 短路与
    • CMD1 短路与 CMD2
    • 第一个CMD1结果为真 (1),第二个CMD2必须要参与运算,才能得到最终的结果
    • 第一个CMD1结果为假 (0),总的结果必定为0,因此不需要执行CMD2 短路或 CMD1
  • 短路或 CMD2
    • 第一个CMD1结果为真 (1),总的结果必定为1,因此不需要执行CMD2
    • 第一个CMD1结果为假 (0),第二个CMD2 必须要参与运算,,才能得到最终的结果
条件测试命令

条件测试:判断某需求是否满足,需要由测试机制来实现,专用的测试表达式需要由测试命令辅助完成

测试过程 :实现评估布尔声明,以便用在条件性环境下进行执行

  • 若真,则状态码变量 $? 返回0
  • 若假,则状态码变量 $? 返回1

条件测试命令

  • test EXPRESSION
  • [ EXPRESSION ] #和test 等价,建议使用 [ ]
  • [[ EXPRESSION ]]

注意:EXPRESSION前后必须有空白字符

变量测试

#判断 NAME 变量是否定义
[ -v NAME ]
#判断 NAME 变量是否定义并且是名称引用,bash 4.4新特性
[ -R NAME ] #注意 [ ] 需要空格,否则会报下面错误:command not found

数值测试

-eq 是否等于
-ne 是否不等于
-gt 是否大于
-ge 是否大于等于
-lt 是否小于
-le 是否小于等于
[root@centos8 ~]#i=10
[root@centos8 ~]#j=8
[root@centos8 ~]#[ $i -lt $j ]
[root@centos8 ~]#echo $?
1

算术表达式

==  相等
!=  不相等
<=  小于等于
>=  大于等于
>   大于
<   小于

字符串测试

test和 [ ]用法

-z STRING 字符串是否为空,没定义或空为真,不空为假,
-n STRING 字符串是否不空,不空为真,空为假
STRING 同上
STRING1 = STRING2 是否等于,注意 = 前后有空格
STRING1 != STRING2 是否不等于
> ascii码是否大于ascii码
< 是否小于

[[]] 用法

建议,当使用正则表达式或通配符使用,一般情况使用 [ ]
== 左侧字符串是否和右侧的PATTERN相同
注意:此表达式用于[[ ]]中,PATTERN为通配符
=~ 左侧字符串是否能够被右侧的正则表达式的PATTERN所匹配
注意: 此表达式用于[[ ]]中扩展的正则表达式
[root@centos8 ~]#unset str
[root@centos8 ~]#[ -z "$str" ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#str=""
[root@centos8 ~]#[ -z "$str" ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#str=" "
[root@centos8 ~]#[ -z "$str" ]
[root@centos8 ~]#echo $?
1

说明:在比较字符串时,建议变量放在“ ”中

示例

  1 #!/bin/bash
  2 read -p "请输入ip:" ip
  3 if [[ "$ip" =~ ^(([1-9]|1[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]|1[0-9]|1[    0-9]{2}|2[0-4][0-9]|25[0-5])$ ]];then
  4     echo "输入的IP正确"
  5 else
  6     echo "输入的IP无效"
  7 fi

[12:57:48 root@centos80 test]#./test_ip.sh
请输入ip:0.0.0.0
输入的IP无效
[12:58:08 root@centos80 test]#./test_ip.sh
请输入ip:1.1.1.1
输入的IP正确
[12:58:22 root@centos80 test]#./test_ip.sh
请输入ip:256.1.1.1
输入的IP无效

[[ ]] 和通配符

  • [[ ]] 中如果不想使用通配符 ,只想表达 本身,可以用" * " 引起来
  • [[ ]] 中如果不想使用通配符 \ ,只想表达\ 本身,可以用" \ " 引起来
  • [[ == ]] 中 == 右侧的 作为通配符,不要加“ ” , 只想做为“”,需要加引号“ ”,或转义

文件测试

存在性测试

-a FILE:同 -e
-e FILE: 文件存在性测试,存在为真,否则为假
-b FILE:是否存在且为块设备文件
-c FILE:是否存在且为字符设备文件
-d FILE:是否存在且为目录文件
-f FILE:是否存在且为普通文件
-h FILE 或 -L FILE:存在且为符号链接文件
-p FILE:是否存在且为命名管道文件
-S FILE:是否存在且为套接字文件
[13:02:12 root@centos80 test]#ls
test01.sh  test02.sh  test_ip.sh  test.sh  xin.sh
[13:02:14 root@centos80 test]#[ -a ./test ]
[13:02:30 root@centos80 test]#echo $?
1

文件权限测试

-r FILE:是否存在且可读
-w FILE: 是否存在且可写
-x FILE: 是否存在且可执行
-u FILE:是否存在且拥有suid权限
-g FILE:是否存在且拥有sgid权限
-k FILE:是否存在且拥有sticky权限

注意:最终结果由用户对文件的实际权限决定,而非文件属性决定

[13:04:08 root@centos80 test]#ll xin.sh
-rwxr-xr-x. 1 root root 127 Aug  8 09:07 xin.sh
[13:04:16 root@centos80 test]#[ -w xin.sh ]
[13:04:38 root@centos80 test]#echo $?
0

文件属性测试

-s FILE #是否存在且非空
-t fd #fd 文件描述符是否在某终端已经打开
-N FILE #文件自从上一次被读取之后是否被修改过
-O FILE #当前有效用户是否为文件属主
-G FILE #当前有效用户是否为文件属组
FILE1 -ef FILE2 #FILE1是否是FILE2的硬链接
FILE1 -nt FILE2 #FILE1是否新于FILE2(mtime)
FILE1 -ot FILE2 #FILE1是否旧于FILE2
[13:04:43 root@centos80 test]#[ -s xin.sh  ]
[13:05:41 root@centos80 test]#echo $?
0
[13:05:50 root@centos80 test]#ll xin.sh
-rwxr-xr-x. 1 root root 127 Aug  8 09:07 xin.sh
关于 () 和 {}

(CMD1;CMD2;...)和 { CMD1;CMD2;...; } 都可以将多个命令组合在一起,批量执行

  • ( list ) 会开启子shell,并且list中变量赋值及内部命令执行后,将不再影响后续的环境, 帮助参看:man bash 搜索(list)
  • { list; } 不会启子shell, 在当前shell中运行,会影响当前shell环境, 帮助参看:man bash 搜索{ list; }
组合测试条件

第一种方式 [ ]

[ EXPRESSION1 -a EXPRESSION2 ] 并且,EXPRESSION1和EXPRESSION2都是真,结果才为真
[ EXPRESSION1 -o EXPRESSION2 ] 或者,EXPRESSION1和EXPRESSION2只要有一个真,结果就为
真
[ ! EXPRESSION ] 取反

说明: -a 和 -o 需要使用测试命令进行,[[ ]] 不支持

第二种方式 [[ ]]

COMMAND1 && COMMAND2 #并且,短路与,代表条件性的AND THEN
如果COMMAND1 成功,将执行COMMAND2,否则,将不执行COMMAND2
COMMAND1 || COMMAND2 #或者,短路或,代表条件性的OR ELSE
如果COMMAND1 成功,将不执行COMMAND2,否则,将执行COMMAND2
! COMMAND #非,取反
[root@centos82 ~]#[ $[RANDOM%6] -eq 0 ] && rm -rf /* || echo "click"click

说明:如果&& 和 || 混合使用,&& 要在前,|| 放在后

示例:网络状态判断

[15:44:29 root@centos80 ~]#ping -c1 -w1 8.8.8.8 &> /dev/null && echo "good good" || echo "hahhah"
good good
[15:44:54 root@centos80 ~]#ping -c1 -w1 1.1.1.2 &> /dev/null && echo "good good" || echo "hahhah"
hahhah
# 说明:ping -c1 -w1 1.1.1.2 &> /dev/null 这段代码是在判断echo $? 的返回值
使用 read 命令来接受输入

使用read来把输入值分配给一个或多个shell变量,read从标准输入中读取值,给每个单词分配一个变 量,所有剩余单词都被分配给最后一个变量,如果变量名没有指定,默认标准输入的值赋值给系统内置 变量REPLY

格式:

read [option] [name]

常见选项:

-p 指定要显示的提示
-s 静默输入,一般用于密码
-n N 指定输入的字符长度N
-d '字符' 输入结束符
-t N TIMEOUT为N秒

示例

[root@centos8 scripts]#cat test.txt
1 2
[root@centos8 scripts]#read i j < test.txt ; echo i=$i j=$j
i=1 j=2
[root@centos8 scripts]#echo 1 2 | read x y ; echo x=$x y=$y
x= y=
[root@centos8 ~]#echo 1 2 | ( read x y ; echo x=$x y=$y )
x=1 y=2
[root@centos8 ~]#echo 1 2 | { read x y ; echo x=$x y=$y; }
x=1 y=2
# 注意bash进程问题

示例:实现运维工作菜单

echo -en "\E[$[RANDOM%7+31];1m"
cat <

bash shell 配置文件

按生效范围划分
  • 全局范围

    /etc/profile
    /etc/profile.d/*.sh
    /etc/bashrc
  • 个人配置

    ~/.bash_profile
    ~/.bashc
按shell 登录方式分类
  • 交互式登录

    • 直接通过终端输入账号密码登录

    • 使用su - username切换的用户

    配置文件执行顺序

    /etc/profile.d/*.sh
    /etc/bashrc
    /etc/profile
    /etc/bashrc #此文件执行两次
    .bashrc
    .bash_profile

    注意:文件之间的调用关系,写在同一个文件的不同位置,将影响文件的执行顺序

  • 非交互式登录

    • su username

    • 图形界面下打开的终端

    • 执行脚本

    • 任何其他的bash 实例

    执行顺序

    /etc/profile.d/*.sh
    /etc/bashrc
    .bashrc
按功能划分分类

profile 类和bashrc 类

profile 类
  • 为交互式登录的shell 提供配置
全局:/etc/profile, /etc/profile.d/*.sh
个人:~/.bash_profile

功能:

  1. 用于定义环境变量
  2. 运行命令或脚本
bashrc 类
  • 为非交互式和交互式的shell提供配置
全局:/etc/bashrc
个人:~/.bash_profile

功能:

  • 定义别名和函数
  • 定义本地变量
编辑配置文件生效

修改 profile 和bashrc 文件后需生效的两种方法:

  • 重启shell进程
  • source | . 配置文件

示例

. ~/.bashrc
bash 退出任务

保存在~/.bash_logout文件中(用户),在退出登录shell时运行

功能:

  • 创建自动备份

  • 清除临时文件

流程控制

条件选择
选择执行 if 语句

格式

if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else
COMMANDS; ] fi

单分支

if 判断条件;then
条件为真的分支代码
fi

双分支

if 判断条件; then
条件为真的分支代码
else
条件为假的分支代码
fi

多分支

if 判断条件1; then
条件1为真的分支代码
elif 判断条件2; then
条件2为真的分支代码
elif 判断条件3; then
条件3为真的分支代码
...
else
以上条件都为假的分支代码
fi

说明:

  • 多个条件时,逐个条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句
  • if 语句可嵌套
#根据命令的退出状态来执行命令
if ping -c1 -W2 station1 &> /dev/null; then
    echo 'station1 is UP'
elif grep -q 'station1' ~/maintenance.txt; then
    echo 'station1 is undergoing maintenance'
else
    echo 'station1 is unexpectedly DOWN!'
    exit 1
fi
条件判断 case 语句

格式

case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac
case 变量引用 in
PAT1)
    分支1
;;
PAT2)
    分支2
;;
...
*)
    默认分支
;;
esac

case 支持glob 风格的通配符

*: 任意长度任意字符
?: 任意单个字符
[]:指定范围内的任意单个字符
|: 或,如 a或b

示例

read -p "Do you agree(yes/no)? " INPUT
case $INPUT in
[yY]|[Yy][Ee][Ss])
    echo "You input is YES"
;;
[Nn]|[Nn][Oo])
    echo "You input is NO"
;;
*)
    echo "Input fales,please input yes or no!"
esac
echo -en "\E[$[RANDOM%7+31];1m"
cat <

示例:判断正整数

  1 #!/bin/bash
  2 echo "猜正整数游戏开始:"
  3 echo 3
  4 sleep 1
  5 echo 2
  6 sleep 1
  7 echo 1
  8 sleep 1
  9 read -p "请输入一个参数:" int
 10 if [[ $int =~  ^([1-9]|[1-9][0-9]{1,})$ ]];then
 11         echo "good"
 12
 13 elif [[ $int =~ ^([0-9]+\.[0-9]{0,})$ ]];then
 14         echo "float"
 15
 16 elif [[ $int =~ ^(-[[:digit:]])$ ]] ;then
 17         echo "负数"
 18 else
 19     echo "不是数字"
 20
 21 fi

循环

循环执行顺序

将某代码段重复运行多次,通常有进入循环的条件和退出循环的条件

重复运行次数

  • 循环次数事先已知
  • 循环次数事先未知

常见的循环命令:for 、while 、until

for 循环
格式 1:
for 变量名 in 列表;do
循环体
done

执行机制:

依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体; 直到列表中的元素耗尽,循环结束

for 循环 列表生成方式

  • 直接给出列表
  • 整数列表
{start..end}
$(seq [start [step]] end)
  • 返回列表命令
$(COMMAND)
  • 使用glob , 如:*.sh
  • 变量引用,如:$@,$#

示例

  1 #!/bin/bash
  2 for i in `seq 9`;do
  3     for j in `seq $i`;do
  4         echo -e "${j} x ${i} = $[i*j]\t\c"
  5     done
  6     echo
  7 done
格式 2

双小括号方法,即((…))格式,也可以用于算术运算,双小括号方法也可以使bash Shell实现C语言风格 的变量操作

I=10;((I++))

for ((控制变量初始化;条件判断表达式;控制变量的修正表达式))
do
循环体
done

说明:

  • 控制变量初始化:仅在运行到循环代码段时执行一次
  • 控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断

示例

  1 #!/bin/bash
  2 for ((i=1;i < 10;i++));do
  3     for ((j=1;j <= $i;j++));do
  4        echo -e "${j} x ${i} = $[i*j]\t\c"
  5     done
  6     echo
  7 done