# Shell 编程
# 正则表达式
# 正则表达式与通配符
- 正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配。grep、awk、sed 等命令可以支持正则表达式。
- 通配符用来匹配符合条件的文件名,通配符是完全匹配。ls、find、cp 这些命令不支持正则表达式,所以只能使用 shell 自己的通配符来进行匹配了。
# 基础正则表达式
"*" 表示前一个字符匹配 0 次,或任意多次
[root@localhost ~]# grep "a*" test_rule.txt # 匹配所有内容,包括空白行 | |
[root@localhost ~]# grep "aa*" test_rule.txt # 匹配最少包含有一个 a 的行 | |
[root@localhost ~]# grep "aaa*" test_rule.txt # 匹配最少包含两个连续 a 的字符串 | |
[root@localhost ~]# grep "aaaaa*" test_rule.txt # 则会匹配最少包含四个连续 a 的字符串 |
"." 匹配除了换行符外任意一个字符
[root@localhost ~]# grep "s..d" test_rule.txt # 匹配在 s 和 d 这两个字母之间一定有两个字符的单词 | |
[root@localhost ~]# grep "s.*d" test_rule.txt # 匹配在 s 和 d 字母之间有任意字符 | |
[root@localhost ~]# grep ".*" test_rule.txt # 匹配所有内容 |
"^" 匹配行首,"$" 匹配行尾
[root@localhost ~]# grep "^M" test_rule.txt # 匹配以大写 “M” 开头的行 | |
[root@localhost ~]# grep "n$" test_rule.txt # 匹配以小写 “n” 结尾的行 | |
[root@localhost ~]# grep -n "^$" test_rule.txt # 会匹配空白行 |
"[]" 匹配中括号中指定的任意一个字符,只匹配一个字符
[root@localhost ~]# grep "s [ao] id" test_rule.txt # 匹配 s 和 i 字母中,要不是 a、要不是 o | |
[root@localhost ~]# grep "[0-9]" test_rule.txt # 匹配任意一个数字 | |
[root@localhost ~]# grep "^[a-z]" test_rule.txt # 匹配用小写字母开头的行 |
"[^]" 匹配除中括号的字符以外的任意一个字符
[root@localhost ~]# grep "^[^a-z]" test_rule.txt # 匹配不用小写字母开头的行 | |
[root@localhost ~]# grep "^[^a-zA-Z]" test_rule.txt # 匹配不用字母开头的行 |
"\" 转义符
[root@localhost ~]# grep "\.$" test_rule.txt # 匹配使用 "." 结尾的行 |
# 字符截取命令
# cut 字段提取命令
[root@localhost ~]# cut [选项] 文件名
选项:
-f 列号: 提取第几列
-d 分隔符: 按照指定分隔符分隔列
默认以制表符作为分隔符。
# printf 命令
[root@localhost ~]# printf '输出类型输出格式' 输出内容
输出类型:
% ns: 输出字符串,n 是数字指代输出几个字符
% ni: 输出整数,n 是数字指代输出几个数字
%m.nf: 输出浮点数,m 和 n 是数字,指代输出的整数位数和小数位数。如 %8.2f 代表共输出 8 位数,其中 2 位是小数,6 位是整数。
输出格式:
\a: 输出警告声音
\b: 输出退格键,也就是 Backspace 键
\f: 清除屏幕
\n: 换行
\r: 回车,也就是 Enter 键
\t: 水平输出退格键,也就是 Tab 键
\v: 垂直输出退格键,也就是 Tab 键
[root@localhost ~]# printf '%s %s %s\n' 1 2 3 4 5 6
[root@localhost ~]# printf '%s' $(cat student.txt)
在 awk 命令的输出中支持 print 和 printf 命令
- print:print 会在每个输出之后自动加入一个换行符(Linux 默认没有 print 命令)
- printf:printf 是标准格式输出命令,并不会自动加入换行符,如果需要换行,需要手工加入换行符
# awk 命令
[root@localhost ~]# awk '条件1{动作1} 条件2{动作2}...' 文件名
条件(pattern):
一般使用关系表达式作为条件:
x>10 判断变量 x 是否大于 10
x>=10 大于等于
x<=10 小于等于
动作(Action):
格式化输出
流程控制语句
[root@localhost ~]# df -h | awk '{printf $1 "\t" $5 "\t" $6 "\n"}'
BEGIN
[root@localhost ~]# awk 'BEGIN{printf "This is a transcript \n"} {printf \$2 "\t" \$6 "\n"}' student.txt
读取文本之前执行动作
FS 内置变量
[root@localhost ~]# cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN {FS=":"} {printf \$1 "\t" \$3 "\n"}'
指定文本的分隔符
END
[root@localhost ~]# awk 'END{printf "The End\n"} {printf \$2 "\t" \$6 "\n"}' stuent.txt
在所有数据处理完之后再执行的动作
关系运算符
[root@localhost ~]# cat student.txt | grep -v Name | awk '$6>=87 {printf $2 "\n"}'
# sed 命令
sed 是一种几乎包括在所有 UNIX 平台(包括 Linux)的轻量级流编辑器。sed 主要是用来将数据进行选取、替换、删除、新增的命令。
[root@localhost ~]# sed [选项] '[动作]' 文件名
选项:
-n: 一般 sed 命令会把所有数据都输出到屏幕,如果加入此选择,则只会把经过 sed 命令处理的行输出到屏幕。
-e: 允许对输入数据应用多条 sed 命令编辑
-i: 用 sed 的修改结果直接修改读取数据的文件,而不是由屏幕输出
动作:
a: 追加,再当前行后添加一行或多行。添加多行时,除最后一行外,每行末尾需要用 "\" 代表数据未完结。
c: 行替换,用 c 后面的字符串替换原数据行,替换多行时,除最后一行外,每行末尾需用 "\" 代表数据未完结。
i: 插入,在当期行前插入一行或多行。插入多行时,除最后一行外,每行末尾需要用 "\" 代表数据未完结。
d: 删除,删除指定的行。
p: 打印,输出指定的行。
s: 字串替换,用一个字符串替换另一个字符串。格式为 “行范围 s / 旧字串 / 新字串 /g”(和 vim 中的替换格式类似)。
# 字符处理命令
# 排序命令 sort
[root@localhost ~]# sort [选项] 文件名
选项:
-f: 忽略大小写
-n: 以数值型进行排序,默认使用字符串型排序
-r: 反向排序
-t: 指定分隔符,默认是分隔符是制表符
-k n [,m]: 按照指定的字段范围排序。从第 n 字段开始,m 字段结束(默认到行尾)
[root@localhost ~]# sort -t ":" -k 3,3 /etc/passwd
#指定分隔符是 ":",用第三字段开头,第三字段结尾排序,就是只用第三字段排序。
# 统计命令 wc
[root@localhost ~]# wc [选项] 文件名
选项:
-l: 只统计行数
-w: 只统计单词书
-m: 只统计字符数
# 条件判断
# 按照文件类型进行判断
两种判断格式
[root@localhost ~]# test -e /root/install.log
[root@localhost ~]# [ -e /root/install.log ]
# 按照文件权限进行判断
# 两个文件之间进行比较
# 两个整数之间进行比较
# 字符串的判断
# 多重条件判断
# 流程控制
# if 语句
单分支 if 条件语句
if [ 条件判断式 ];then | |
程序 | |
fi | |
#或者 | |
if [条件判断式] | |
then | |
程序 | |
fi |
单分支条件语句需要注意几个点:
- if 语句使用 fi 结尾,和一般语言使用大括号结尾不同
- [条件判断式] 就是使用 test 命令判断,所以中括号和条件判断式之间必须由空格
- then 后面跟符合条件之后执行的程序,可以放在 [] 之后,用 ";" 分隔。也可以换行写入,就不需要 ";" 了
双分支 if 条件语句
if [ 条件判断式 ] | |
then | |
条件成立时,执行的程序 | |
else | |
条件不成立时,执行的另一个程序 | |
fi |
多分支 if 条件语句
if [ 条件判断式1 ] | |
then | |
当条件判断式1成立时,执行程序1 | |
elif [ 条件判断式2 ] | |
then | |
当条件判断式2成立时,执行程序2 | |
#... 省略更多条件... | |
else | |
当所有条件都不成立时,最后执行此程序 | |
fi |
# case 语句
多分支 case 条件语句
case 语句和 if...elif...else 语句一样都是多分支条件语句,不过和 if 多分支条件语句不同的是,case 语句只能判断一种条件关系,而 if 语句可以判断多种条件关系。
case $变量名 in | |
"值1") | |
如果变量的值等于值1,则执行程序1 | |
;; | |
"值2") | |
如果变量的值等于值2,则执行程序2 | |
;; | |
...省略其他分支... | |
*) | |
如果变量的值都不是以上的值,则执行此程序 | |
;; | |
esac |
# for 循环
语法 1
for 变量 in 值1 值2 值3... | |
do | |
程序 | |
done |
语法 2
for ((初始值;循环控制条件;变量变化)) | |
do | |
程序 | |
done |
# while 循环与 until 循环
while 循环
while 循环是不定循环,也称作条件循环。只要条件判定式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止。这就和 for 的固定循环不太一样了。
while [ 条件判断式 ] | |
do | |
程序 | |
done |
until 循环
until 循环,和 while 循环相反,until 循环时只要条件判断式不成立则进行循环,并执行循环程序。一旦循环条件成立,则终止循环。
until [ 条件判断式 ] | |
do | |
程序 | |
done |