19 过滤器:选取、排序、组合和变换
19.1 选取包含特定模式的行:grep
相关过滤器:look,strings
语法:
grep [-cilLnrsvwx] pattern [file...]
pattern是要搜索的模式
例:
显示在下午或者晚上登录系统的所有用户:
w -h | grep pm (-h抑制了标题)
只显示用户标识:
w -h | grep pm | cut -c1-8
19.2 最重要的grep选项
-c (count,统计)
例:
统计/etc目录中子目录的数量:
ls -F /etc | grep -c "/"
-i(ingore(忽略大小写区别)
-n(num,每行前面写行号)
-l(list,列举文件名):希望在不止一个文件中查找,显示包含模式的文件
例: grep -l Harley names oldnames newnames
-L(和list相反):显示不包含模式的文件
-w:只希望搜索完整的单词
-v(reverse,相反):选取不包含指定模式的所有行
-x:查找占用整行的那些行
-r(recursive,递归):搜索整个目录树
例:grep -r pattern directory
-s(suppress,抑制):搜索时不显示警告信息
例:grep -rs 'shutdown notq' /
19.3 grep变体:fgrep、egrep
fgrep:快速版本的grep,只搜索固定字符的字符串,不能使用正则表达式,现以不经常使用。
egrep:扩展版本的grep,支持功能更强大的“扩展正则表达式”。同:gerp -E
19.4 选取以特定模式开头的行:look
相关过滤器:grep
语法:look [-df] pattern file...
-d(dictory,字典):忽略标点和特殊字符
-f(fold,等同):忽略大小写
注意:look不能从标准输入中读取数据,它必须从一个或多个文件中获取数据,所以严格地讲,look不是过滤器。基于这个原因,可以在管道线的开头使用look,但不能在中间使用。
例:
sort frosh soph junior senior > evalutions
look A evaluations | colrm 1 3 > a-professors
19.5 使用look和grep的时机
19.6 查找以特定模式开头的所有单词:look
look pattern
19.7 排序程序:sort
相关过滤器:tsort,uniq
语法:
sort [-dfnru] [-o oufile] [infiles...]
例:
cat newnames oldnames | grep Harley | sort | less
19.8 控制数据排序的顺序:sort -dfn
-d(dictory):只查看字母、数字和空白符
-f(fold),忽略大小写
-n(numeric),识别行开头或者字段开头的数字,并按数字进行排序
-r(reverse),反向排序
-u(unique),查找相同的行
19.9 检查数据是否有序:sort -c
sort -c[u] [file]
输出:没显示,说明数据是有序的;显示,无序。
19.10 ASCII码;排序序列
Unix类型 显示ASCII码命令
Linux man ascii
FreeBSD less /usr/share/misc/ascii
Solaris less /usr/pub/ascii
记住ASCII码字符顺序:空格,数字,大写,小写,“SNUL”
19.11 区域涩会只和排序序列
LC——COLLATE环境变量;指定使用哪一种排序序列
locale:显示系统所有区域设置当前值
locale -a :显示系统支持那些区域设置
区域设置:
C/POSIX
en_US
排序表见:P420
19.12 查找重复行:uniq
相关过滤器:sort
语法:uniq [-cdu] [infile] [outfile]]
-d:只查看重复行
-u:只查看非重复行
-c:统计每行出现的次数
例:
sort file1 file2 file3 | uniq
cat file1 file2 file3 | sort | uniq
19.13 合并两个文件中的有序数据:join
相关过滤器:colrm,cut,paste
语法:join [-i] [-a1|v1] [-a2|-v2] [-1 field1] [-2 field2] file1 file2
19.14 由偏序创建全序:tsort
相关过滤器:sort
语法:tsort [file]
ubuntu:~/桌面$ cat >t
A B
B C
D E
C D
ubuntu:~/桌面$ tsort t
A
B
C
D
E
注意:有序对最好不要形成环。
19.15 在二进制文件中搜索字符串:strings
相关过滤器:grep
语法:strings [-length] [file...]
length:要显示字符串的最小长度
功能:为了让程序员显示嵌在可执行程序和对象文件中的字符串。
例:
strings -7 /usr/bin/sort | sort -iu
19.16 转换字符:tr
相关过滤器:sed
tr(translate,转换)程序可以对字符执行3种不同运算:
1.将字符改变成其他字符
2.如果要转换的字符连续出现不知一次,用一个单独的字符替换
3.删除指定的字符
语法:tr [-cds] [set1 [set2]]
set是字符组
注:tr是纯过滤器,只从标准输入读取数据,仅向标准输出写入数据。如果希望从文件中读取(写入)数据,则必须重定向到标准输入(输出)。
例:
tr a A < oldfile
tr a A < oldflle > newfile
tr ':;?' /. < old > new 注意引号中不要有空格,‘.’前面有转义。
tr A-Z a-z < old > new 同下一个等价
tr [:upper:] [:lower:] < old > new
tr 0-9 A-J < old > new
tr [:digit:] A-J < old > new
19.17 转换不可显示字符
代码 控制键 八进制码 名称
/b ^H /010 退格
/t ^I /011 制表符
/n ^J /012 新行/换行
/r ^M /015 回车
// - - 反斜线
例:
tr '/r' '/n' < macfile > unixfile 同下
tr '/015' '/012' < macfile > unixfile
tr 't' ' ' < olddata > newdata 同下
tr '/011' ' ' < olddata > newdata
19.18 转换字符:高级话题
语法: tr [-cds] [set1 [set2]]
-s(squeeze,挤压):告诉tr第一组中的多个字符应该替换为一个单独的字符
例:tr -S 0-9 X < oldfile > newfile
-d:删除指定的字符
例:tr -d '()' < oldfile > newfile
-c(complement,补数):告诉tr匹配所有不在第一组中的字符。
例:将除空格和行字符之外的所有字符都替换为X
tr -c ' /n' X < olddata > newdata
综合示例:希望统计两个文件中使用的单词的数量。
策略: 1.使用cat组合文件
2.使用tr将每个单词放在一个单独的行上
3.使用sort对行进行排序,并消除重复行
4.使用wc统计剩余的数量
cat file1 file2 | tr -cs [:alpha:]/' "/n" | sort -fu | wc -l
统计一组输入数据所包含的单词的数量:
cat file1... | tr -cs [:alpha:]/' "/n" | sort -fu > file
19.19 非交互式文本编辑:sed
语法:sed [-i] command | -e command... [file...]
-i(in-place,原地):先将输出保存到一个临时文件,一旦所有的数据都处理完,sed就将临时文件复制到原始文件,最终的效果就是改变了原始文件,但前提是sed在执行的过程中没有出错。
使用方法:
1.让sed从文件中读取输入
2.使用sed在管道线中作为过滤器
sed是目前为止功能最强大的过滤器,它不只是单用途的程序,它实际上是一个可移植的、与shell无关的语言解释器。
例:sed -i 's/harley/Harley/g' names
注:使用sed -i时需特别小心,因为它对输入文件的改变是永久性的。
提示:在使用sed改变文件之前,最好先运行一个没有-i选项的程序预览一下改变后的状况:
sed 's/xx/XXX/g' file | less
19.20 使用sed进行替换
相关过滤器:tr
s命令的语法:
[/address|pattern/]s/search/replacement/[g]
address是输入流中一个或多个地址,pattern是一个字符串,search是正则表达式,replacement是替换文本,g代表“global,全局”。
默认情况下只改变每行第一个出现的匹配字符串,加上g后改变所有的。
示例: 将一个Windows格式的文本文件改为Unix的,即将文本行末尾的“回车新行”(^M^J)改为“新行”(^J).
此时无法用tr,因为这里是将两个字符改为一个字符,tr只能将一个字符改成另外一个字符。
sed 's/.$//' winfile > unixfile
解释:'.'匹配任何单独的字符,'$'匹配行的末尾,搜索字符串'.$'就是新行字符前面的字符。注意替换字符串是空的,它告诉sed删除搜索字符串。
提示:使用sed删除字符串,只需搜索改字符串,并将它替换为空即可,这是一重要技术!
19.21 告诉sed只对指定行进行操作
在命令的前面加一个“地址”。
地址的语法:
number[,number] | /regex/
number是行号,regex是正则表达式
例:
只改变数据流的第5行: sed '5s/harley/Harley/g' names
只改变数据流的第5-10行: sed '5,10s/harley/Harley/g' names
只改变数据流的第最后一行: sed '$s/harley/Harley/g' names
只改变数据流包含“OK”的行: sed '/OK/s/harley/Harley/g' names
只改变数据流包含连个连续数字的行: sed '/[0-9][0-9]/s/harley/Harley/g' names
19.22 使用非常长的sed命令
-f:标识程序文件
例: 运行存储在文件prom中的sed程序,并使用input中的数据:
sed -f prom input
修改一个星期7天的缩写,注意所有行都是连续的(除最后一行):
sed -i /
-e 's/mon/Monday/g' /
-e 's/tue/Tuesday/g' /
-e 's/wed/Wednesday/g' /
-e 's/thu/Thursday/g' /
-e 's/fri/Friday/g' /
-e 's/sat/Saturday/g' /
-e 's/sun/Sunday/g' /
calendar