shell脚本开发之文本操作
系列学完了,这是第二期。(其实应该这个先学的) bash
基础
接下来是有名的第三方工具 (正则表达式 awk sed grep等等)
bash 快捷键
快捷键
英文
功能
Ctrl + A
ahead
行首
Ctrl + E
end
行尾
Ctrl + U
删除光标之前的 所有
字符
Ctrl + K
删除光标之后的 所有
字符
Ctrl + L
clear
清空屏幕
Tab
补全 $PATH
命令,补全文件名
RegExp
正则表达式分两类:
基本正则表达式,BRE对应的字符有:^$.[]*
扩展正则表达式,ERE在BRE基础上,加上:(){}?+|
等字符
正则表达式仅支持 (sed, awk, grep)
工具
描述
grep
文本过滤工具 (模式 pattern) 工具
sed
流编辑器 (stream editor) 文本编辑工具
awk
Linux 文本报告生成器 (格式化文本) gawk
BRE 集合
字符
描述
^
尖角号,用于模式的最左侧 --> "^yu"
匹配以 yu
单词开头的行
$
美元符,用于模式的最右侧 --> "yu$"
匹配以 yu
单词结尾的行
^$
组合符,表示空行( ^
后面什么也没写,为空。$
前面什么也没写,为空。开头结尾什么都没有)
.
匹配任意一个且只有一个字符,不能匹配空行
\
转义字符,让特殊含义的字符,现出圆形,还原本意。例如 \.
代表小数点
*
匹配前一个字符(连续出现)0次或1次以上,重复0次代表空,即匹配所有内容 --> a*
匹配 a
0次或多次
.*
组合符,匹配所有内容
^.*
组合符,匹配任意多个字符开头的内容
.*$
组合符,匹配以任意多个字符结尾的内容
[abc]
匹配 []
集合内的任意一个字符,a
或 b
或 c
,可以写成 [a-c]
[^abc]
匹配除了 ^
后面的任意字符,a
或 b
或 c
,^
表示对 [abc]
的取反
ERE 集合
grep 命令需要使用参数 -E
才生效
egrep 不推荐使用,用 grep -E
替代
grep 不加参数,得在特殊字符前面加 \
反斜杠,识别为正则
字符
描述
+
匹配前一个字符1次或多次,前面字符至少出现1次
[:/]+
匹配括号内的 :
或者 /
字符1次或者多次
?
匹配前一个字符0次或1次,前面字符可有可无
|
表示或者,同时过滤多个字符串
()
分组过滤,被括起来的内容表示一个整体
a{n,m}
匹配前一个字符最少n次,最多m次
a{n,}
匹配前一个字符最少n次
a{n}
匹配前一个字符正好n次
a{,m}
匹配前一个字符最多m次
grep
全拼:Global search REgular expression and Print out the line
作用:文本搜索工具,根据用户指定得模式(过滤条件)对目标文本逐行进行匹配检查,打印匹配到的行
模式:由正则表达式的元字符及文本字符所编写出的过滤条件
1 2 3 4 5 6 7 8 语法: grep [options] [pattern] file 命令 参数 匹配模式 文件数据 -i:ignorecase,忽略大小写 -o:仅显示匹配到的字符本身 -v:--invert-match,显示不能被模式匹配到的行 -E:支持使用扩展的正则表达式元字符 -q:--quiet,--silent 静默模式,即不输出任何信息
grep命令是linux系统中最重要的命令之一,功能是从文本文件或管道数据流中筛选匹配的行和数据,如果再配合正则表达式,功能十分强大,是Linux运维人员必备的命令
参数选项
解释说明
-v
排除匹配结果
-n
显示匹配行与行号
-i
不区分大小写
-c
只统计匹配的行数
-E
使用egrep命令
–color=auto
为grep过滤结果添加颜色
-w
只匹配过滤的单词
-o
只输出匹配的内容
1 2 3 4 5 6 7 cat /etc/passwd > pwd.txtgrep -i "root" pwd.txt grep -i -n "root" pwd.txt grep -i -c "root" pwd.txt echo -e "\n\n" >> pwd.txtgrep -i -n "^$" pwd.txt grep -i -v "^$" pwd.txt
1 2 3 4 5 6 7 grep -i "^s" pwd.txt grep -n "bash$" pwd.txt grep -n "bash$" pwd.txt -o grep -n ".apt" pwd.txt grep -n ".apt" pwd.txt --color=auto alias grep='grep --color=auto'
1 2 3 4 grep "[a-z]" /etc/lsb-release grep "[A-Z]" /etc/lsb-release grep "[0-9]" /etc/crontab grep "[^a-zA-Z]" /etc/lsb-release
1 2 3 4 grep -E "l+" /etc/lsb-release grep -E "go?d" aa.txt find . -name "*.txt" | grep -E "a|w" grep -E "g(o|)d" aa.txt
1 2 3 4 5 grep -E "(r..t).*\1" /etc/passwd grep -E "o{1,4}" aa.txt grep -E "o{5,}" aa.txt grep -E "o{2}" aa.txt -o grep -E "o{,4}" aa.txt -o
sed
对文件,数据流进行处理,操作,过滤替换转换文本内容。
工作流程:每次一行,放入模式空间(读入内存),然后模式匹配,匹配成功,进行编辑,后输出屏幕,匹配失败输出屏幕。
1 2 # 语法 sed [选项] (sed 内置命令字符) [输入文件]
选项:
参数选项
解释
-n
取消默认 sed
输出,常与 p
命令一起用
-i
直接将修改结果写入文件中,不加参数就是修改内存数据,输出
-e
多次编辑,不需要管道符了
-r
支持正则扩展
常用的内置命令字符
sed 内置命令字符
解释
a
append, 对文本追加,指定行后面添加一行/多行文本
d
Delete, 删除匹配行
i
insert, 表示插入文本,指定行前添加一行/多行文本
p
Print, 打印匹配行内容,与 -n
一起使用
s/exp/xxx/g
匹配正则内容,然后替换内容(支持正则),结尾 g
代表全局匹配
sed 匹配范围
范围
解释
空地址
全文处理
单地址
指定文件某一行
/pattern/
被模式匹配的某一行
范围区间
10,20 十到二十行 10,+5 第十行向下5行。/pattern1/,/pattern2/
步长
1~2 1,3,5,7,9。2~2两个步长,表示2,4,6,8,10 偶数行
1 2 3 4 5 6 7 8 9 sed -n "2,3p" 2.txt sed -n "1~2p" 2.txt sed -n "2,+2p" 2.txt sed "1a=======" 2.txt sed "1i=======" 2.txt sed "1d" 2.txt sed "s/I/Your/g" 2.txt sed "2s/I/Your/g" 2.txt
1 2 3 4 5 sed -n "/linux/p" 2.txt sed -i "/qq/d" 2.txt cat -n 2.txtsed "s@I@Hers@g" 2.txt sed "s#I#His#g" 2.txt
1 2 3 4 5 6 7 8 9 10 11 sed -i "2iMy qq is 123453453" 2.txt cat -n 2.txtsed -e "s/I/My/g" -e "s/123453453/110/g" 2.txt ifconfig eth0 ifconfig eth0 | sed -n "2p" ifconfig eth0 | sed -n "2p" | sed "s/^.*inet//" ifconfig eth0 | sed -n "2p" | sed "s/^.*inet//" | sed "s/net.*$//g" ifconfig eth0 | sed -e "2s/^.*inet//g" -e "2s/net.*$//gp" -n ifconfig eth0 | sed -e "2s/^.*inet//g" -e "2s/net.*$//g" -e "2s/ //gp" -n
awk
有强大的文本格式化能力,处理成专业表格形式。awk最早是在 Unix
上实现。我们用的 awk
是 GUN awk
即 gawk
。awk 更是一门编程语言,支持条件判断,数组,循环等功能。
1 2 3 # 语法 sed [选项] '模式[动作]' 文件 sed options pattern {action} file
Action 指的是动作,awk擅长文本格式化,且输出格式化的结果,因此最常用的动作是 print
和 printf
。
1 2 3 4 for i in {1..10};do for j in {1..5};do echo -n "hello$((i*j) ) " >> 3.txt;done && echo '' >> 3.txt;done ;cat 3.txtcat 3.txt | awk '{print $2}'
我们执行的命令是 awk '{print $2}'
,并没有使用参数和模式,$2
表示输出文本的第二列信息
awk默认以空格为分隔符,且多个空格也识别为一个空格,作为分隔符
awk是按行处理文件,一行处理完毕,处理下一行,根据用户指定的分隔符去工作,没有指定则默认空格
指定分隔符后,awk
把每一行切割后的数据对应到内置变量
1 2 3 $0 表示整行$NF 表示当前分割后的最后一列$(NF-1) 倒数第二列
常用内置变量
内置变量
解释
$n
指定分隔符后,当前记录的第N个字段
$0
完整的输入记录
NF
(number of fiels) 分割后,当前行一共有多少个字段
NR
(number of records) 当前记录数,行数
FS
输入分隔符,默认是空格
OFS
输出分隔符,默认是空格
RS
输入换行符,默认是换行符,指定输入的换行符
ORS
输出换行符,默认是换行符,指定输出的换行符
FNR
各文件分别计数的行号
FILENAME
当前文件名
ARGC
命令行参数的个数
ARGV
数组,保存的是命令行给定的参数
1 2 3 4 awk '{print $0}' 3.txt awk '{print $3}' 3.txt awk '{print $NF}' 3.txt awk '{print $1$3$NF}' 3.txt
1 2 3 awk '{print $1,$3,$NF}' 3.txt awk '{print "第一列:"$1,"第三列:"$3,"最后一列:"$NF}' 3.txt awk '{print}' 3.txt
参数
参数
解释
-F
指定分割字符
-v
定义或修改一个 awk
内部变量
-f
从脚本文件中读取 awk
命令
1 2 3 4 5 6 7 8 9 cat /etc/passwd -n | head -n 5awk 'NR==3' /etc/passwd awk 'NR==3{print $0}' /etc/passwd awk 'NR==3,NR==5{print $0}' /etc/passwd awk '{print NR,$1}' 3.txt awk 'NR==20,NR==23{print NR,$0}' /etc/passwd awk -F ':' 'NR==20,NR==23{print NR,$1}' /etc/passwd ifconfig eth0 | awk 'NR==2{print $2}'
分隔符有两种
输入分隔符,默认空格。变量名是 FS
(field separator)
输出分隔符,OFS
(output field separator)
1 2 3 4 awk -F ':' 'NR==1,NR==4{print $1}' /etc/passwd awk -v FS=":" 'NR==1,NR==4{print $NF}' /etc/passwd awk -v FS=":" -v OFS=" | " 'NR==1,NR==4{print $1,$NF}' /etc/passwd awk -F ":" -v OFS=" | " 'NR==1,NR==4{print $1,$NF}' /etc/passwd
1 2 3 4 awk '{print NR,FNR,$0}' 2.txt 3.txt awk -v RS="." '{print NR,$0}' 2.txt awk -v OFS="---|---" '{print NR,$0}' 2.txt awk -v ORS="---|---" '{print NR,$0}' 2.txt
1 2 3 4 5 6 7 8 awk '{print NR,FILENAME,$0}' 2.txt 3.txt awk 'BEGIN{print "Start AWK !!"} {print ARGV[0],$0}' 2.txt awk 'BEGIN{print "Start AWK !!"} {print ARGV[1],$0}' 2.txt awk -v name="feng" 'BEGIN{print "Start AWK !!"} {print ARGV[0],ARGV[1],ARGV[2],ARGV[3]}' 1.txt 2.txt awk -v name="feng" 'BEGIN{print "Start AWK !!"} {print ARGV[0],ARGV[1],ARGV[2],name}' 1.txt 2.txt a="shell args" awk -v a="$a " 'BEGIN{print a}'
格式化输出
前面我们接触到的awk的输出功能,是print,只能对文本简单的输出,并不能美化或者修改格式
要点:
其中 print 命令的最大不同是,printf 需要指定 format
format 用于指定后面的每个item的输出格式
printf 语句不会自动打印换行符:\n
format 格式的指示符都以%开头,后跟一个字符
format
解释
%c
显示字符的ASCII
%d %i
十进制整数
%e %E
科学计数法显示数值
%f
显示浮点数
%g %G
以科学计数法的格式或浮点数的格式显示数值
%s
显示字符串
%u
无符号整数
%%
显示%自身
-
左对齐,默认右对齐
+
显示数值符号: printf "%+d"
1 2 3 4 5 6 7 awk '{print $0}' 2.txt awk '{printf $0}' 2.txt awk '{printf "%s\n",$1}' 2.txt awk '{printf "%s\n",$0}' 2.txt printf "%s" a b cprintf "%s\n" a b cprintf "== %s ==\n" a b c
1 2 3 awk 'NR==3,NR==5{printf "第一列:%s, 第二列:%s\n", $1,$2}' 3.txt awk -F ':' 'BEGIN{printf "%-10s\t%-10s\t%-10s\t%-10s\t%-10s\t%-10s\t%-10s\n","Username","password","UID","GID","User mark","Home dir","User bash"}NR==1,NR==10{printf "%-10s\t%-10s\t%-10s\t%-10s\t%-10s\t %-10s\t%-10s\n",$1,$2,$3,$4,$5,$6,$7}' /etc/passwd
模式:
awk
是按行处理文本,刚才讲解了 print
动作,现在讲解特殊的 pattern :
BEGIN
和 END
BEGIN模式是处理文本之前需要执行的操作
END模式是处理完所有行之后执行的操作
awk默认是按行处理文本,如果不指定任何模式(条件),awk默认一行行处理
如果指定了模式,只有符合模式的才会被处理
关系运算符
解释
示例
<
小于
x<y
<=
小于等于
x<=y
==
等于
x==y
!=
不等于
x!=y
>=
大于等于
x>=y
>
大于
x>y
~
匹配正则
x~/正则/
!~
不匹配正则
x!~/正则/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 awk 'BEGIN{print "start awk"}NR==3{print "==",$0}END{print "Stop awk"}' 2.txt awk 'NR>=4{print $0}' 2.txt awk 'NR!=4{print $0}' 2.txt awk '/^feng/{print $0}' /etc/passwd awk -F ':' '/^feng/{print $1,$NF}' /etc/passwd awk -F ':' 'BEGIN{printf "%-10s\t%-10s\t%-10s\t%-10s\n","Username","UID","Home dir","U ser bash"}/^feng/{printf "%-10s\t%-10s\t%-10s\t%-10s\n",$1,$2,$6,$7}' /etc/passwdawk -F ':' '/nologin$/{print $0}' /etc/passwd grep "nologin" /etc/passwd -n awk -F ':' '/^ntp/,/^sshd/{print NR,$0}' /etc/passwd awk '{print $1}' access.log | sort -n | uniq | wc -l awk '{print $1}' access.log | sort -n | uniq -c | sort -nr | head 10