今天花了一下午的时间把 sed,awk 的基础用法看了一下。还没工作,现在暂时用的不多,因此写个笔记整理一下,以便之后快速回忆。
要理解 sed 和 awk 的用法,有座大山必须要先搬走,那就是「正则表达式」。正则表达式用于文本匹配,对于 sed 、 awk 来说就是要把想处理的目标文本,从茫茫的字海中提取出来。
正则表达式
正则表达式若不经常用那真是屡看屡忘,百试不爽。那么正则表达式应该如何正确记忆呢?-分层
类似算法中的分治思想,记忆正则表达时也可遵循此法。遇到一个大问题时我们可先将问题进行拆分,当将每一小问题都妥善解决时,大问题便也解决了。正则表达的拆分可以这样看:
|表达式 |
|:-:|
|字符串表示|
|单个字符表示|
单个字符表示
- 特定字符表示,就是具体的某一个字符。直接输入该字符就可以。
- 范围内字符,[] <-放在中括号内的字符。如[0-9]表示范围0~9中的一个字符,记住范围内字符是表示其中的一个字符。此外中括号还可放入其他范围如:
- [a-z]表示所有小写字母
- [A-Z]表示所有大写字母
- [a-zA-Z]表示所有字母
- [a-zA-Z0-9_] 表示字类字符,与\w等价。(字类字符可以理解为能给变量命名的字符
- [^a-z]表示除小写字母外的所有字符
- 任意字符 . 点表示任意一个字符
- 其他符号
- ^ 在中括号内表示取反,在中括号外表示单词的开头。
- 元字符:\w 表示字类字符,\W 表示非字类字符,\b 分隔符
字符串表示
单个字符拼凑起来便是字符串,如要查找 /etc/passwd 文件中以 t 开头 g 结尾的记录:
1 | grep 't.*g' /etc/passwd |
注意正则表达式是贪婪匹配,即是它会在一行中找到尽量长的匹配结果。因此在写正则表达式的时候,可能需要我们多加注意。大多时候得到理想的匹配结果,都是经过我们多次修改表达式,来一步一步实现的结果。因此需要耐心细致,思考周全。
表达式
即字符串的组合
- * 表示出现0次或多次,
- + 表示出现1次或多次,
- ?表示出现0次或1次
- {n,m} 重复特定次数,n~m 次
案例一,匹配5~10位的 QQ 号(注意{}需要加转义字符):1
grep '[0-9]\{5,10\}' qq.txt
案例二,匹配15位或18位身份证号,支持带 x (身份证号第一位不为0,() 需要加转移字符,| 逻辑或需要加转义字符):1
grep '^[1-9]\([0-9]\{13\} \| [0-9]{16}\)[0-9xX]$'
sed
MAC 系统上是 BSD 版本的 sed ,和 GNU 的某些操作不一样!!!下文是记录的 GNU 系统下的 sed 命令,若在 MAC 上先装 GNU-SED1
brew install gnu-sed --with-default-names
sed 是流处理编辑器,从文本或管道读取数据到模式空间(临时缓冲区)中,通过 sed 命令处理然后输出。sed 每次只处理一行数据。
sed 处理:
- 如何进行文本处理的
- 常用命令
- 高级操作命令
如何进行文本处理呢?
1.正则选定文本 -> 2. sed进行处理
命令行模式:1
sed [option] 'command' files
options: -e, -n(quiet)
command: 行定位(正则) + sed 命令
行定位:
- 定位1行: x, /patterm/
- 定位多行x,y
- 不选某行 x!
- 定位间隔 first~step
- a新增行,c 替代行,d 删除行,s 替换(分割符/ 、#),g 全局标志
打印第十行1
sed -n '10p' /etc/passwd
打印第10~20行1
sed -n '10,20p' /etc/passwd
打印日志中 Error 的行, //是正则表达式部分1
sed -n '/Error/p' log.txt
打印主机网络接口的 ip 地址1
2
3
4
5
6
7
8
9
10先查看接口信息
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
ether 8c:85:90:cb:10:70
inet6 fe80::801:55c8:cc5e:acc6%en0 prefixlen 64 secured scopeid 0x6
inet 172.17.131.14 netmask 0xfffff000 broadcast 172.17.143.255
nd6 options=201<PERFORMNUD,DAD>
media: autoselect
status: active
----------------------------
ifconfig en0 | sed -n '/inet /p' | sed 's/inet \([0-9.]\+\).*/\1/'
高级操作命令
- {} 多个 sed 命令,用;分开
& 替换固定字符
案例,小写转大写1
sed 's/\(\w\+\):.*/\1/' passwd | sed 's/.*/\U&/'
-r 复制指定文件到匹配行 (插入)
1
sed '1r abc.txt' 123.txt # abc.txt文件拷贝到目标文件第一行之后
-w 复制匹配行拷贝到指定文件里 (改写源文件)
- -q 退出
awk
可编程,处理灵活。方便统计文本,制表。
- awk 的行处理方式与格式
- awk 内嵌参数应用
- awk 内嵌程序代码应用
awk 处理方式
- 一次处理一行
- awk 可对每行切片处理
命令行格式:1
awk [options] 'command' files
基本格式 + 扩展格式 : pattern {awk 操作命令}
内置参数
- 内置变量, $0 表示当前行,$1表示第一个字段,$2表示第二个字段以此类推
- 分隔符, -F : ‘分隔符’
- NR: 每行记录号
- NF:字段数数量变量
- FILENAME:正在处理文件的文件名
案例1,打印行号,列数,用户名1
awk -F ':' '{print NR, NF, $1}' /etc/passwd
or1
awk -F ':' '{printf("%s, %s, %s\n", NR, NF, $1)}' /etc/passwd
案例2,显示/etc/passwd 中用户 id 大于100的行号和用户名1
awk -F ':' '{if ($3 > 100) print $3, $1}' /etc/passwd
内嵌程序应用
逻辑判断式: pattern {awk 命令}
pattern 表示为: 正则表达式;逻辑表达式
- ~表示匹配正则表达式,!~表示不匹配正则表达式
- ==, != , < , > 常见的判断逻辑
案例1,打印出日志文件中为 Error 行的时间戳1
sed '/Error/p' log | awk '{print $1}'
or1
awk '/Error/{print $1}' log
案例2,统计主机处于连接状态和监听状态的描述符数量1
netstat -anp | awk '$6~/CONNECTED|LISTEN/{sum[$6]++}END{for(i in sum) print i, sum[i]}'