Shell脚本学习指南之文本处理工具
4.1 排序文本
4.1.1 行的排序
未提供命令行选项时,整个记录会根据当前locale所定义的次序排序。
在传统的c locale中,也就是ascii顺序。
4.1.2 以字段排序
-k选项的后面接着的是一个字段编号,或者是一对数字。
每个编号后面都可以接一个点号的字符位置,或修饰符字母。
如果仅指定一个字段编号,则排序键值会自该字段的起始处开始,
一直继续到记录的结尾(而非字段的结尾)。
如果给的是一对用逗号隔开的字段数字,则排序键值将由第一个字段值的起始处开始,
结束于第二个字段值的结尾。使用点号表示字符位置。
-k2.4, 5.6指的是从第二个字段的第四个字符开始比较,一直比到第五个字段的第六个字符。
$ sort -t: -k1,1 /etc/passwd 以用户名称排序
bin:x:1:1:bin:/bin:/sbin/nologin
chico:x:12501:1000:chico marx:/home/chico:/bin/bash
harpo:x:12502:1000:harpo marx:/home/harpo:/bin/ksh
...
$ sort -t: -k3,3nr /etc/passwd 反省uid排序
或-k3nr,3或-k3,3 -n -r都可以。
4.1.3 文本块的排序
有时需要对多行记录组合而成的数据排序。以地址清单为例:
$ cat my-friends
# sortkey: schlo, hans jurgen
hans jurgen schlo
unter den linden 78
d-10117 berlin
germany
# sortkey: jones, adrian
...
技巧是:利用awk识别段落间隔,在每个地址内暂时使用一个未用过的字符取代分行。
sort看到的行就会变成这样:
# sortkey: schlo, hans jurgen^zhans jurgen schlo^zunter den linden 78^z...
cat my-friends | 读取地址文件
awk -v rs=" " '{ gsub("\n", "^z"); print }' | 转换地址为单行
sort -f | 排序地址数据,忽略大小写
awk -v ors="\n\n" '{ gsub("^z", "\n"); print }' | 恢复行结构
grep -v '# sortkey' 删除标记行
1. 函数gsub()为全局性替换(global substitution),类似sed下的s/x/y/g结构。
2. rs变量时输入数据的记录分隔器(record separator)。
通常输入数据以换行隔开,使每行成为单个记录。
rs=" "是一个特殊用法,指的是记录以空行隔开。
3. ors是输出记录分隔器。
注:'{ action }'是对每个字段的操作,而rs,ors都是对记录的设定。
4.1.5 sort的稳定性
sort并不稳定。
4.2 删除重复
sort -u是依据匹配的键值进行消除操作,而非匹配的记录。
uniq有3个好用选项:
-c在每个输出行之前加上该行重复的次数。
-d则用于仅显示重复的行。
-u仅显示未重复的行。
4.3 重新格式化段落
fwt -w 30
4.4 计算行数、字数以及字符数
wc的默认输出是一行报告,包括行数、字数以及字节数。
可用选项:-c(字节数)、-l(行数)、-w(字数)。
$ echo testing one two three | wc -c
1 4 22
$ wc /etc/passwd /etc/group
4.6 提取开头或结尾数行
显示文件列表中每一个的前n条记录:
head -n n [file(s)]
head -n [file(s)]
awk 'fnr <= n' [file(s)]
sed -e nq [file(s)]
sed nq [file(s)]
观察不断增长的系统信息日志,ctrl-c停止tail。
$ tail -n 25 -f /var/log/messages
上一篇: 说说我对企业网站建设的建议
下一篇: ssh expect自动登录的脚本代码