1.文本查找 searching
传统上,有3种程序可以用来查找整个文本文件。
1. grep 基本正则表达式
2. egrep 扩展正则表达式
3. fgrep 快速grep,匹配固定字符串而非正则表达式,它使用优化算法,能更有效的匹配固定字符串。
后来这三个都整合到了grep中。
1.简单的grep
who | grep -F austen
使用-F选项查找固定字符串austen,事实上,只要匹配的模式里未含有正则表达式的Meta字符,则grep默认行为模式就等同于使用了-F:
who | grep austen
2.正则表达
grep [options...] pattern-spec[files...]
用途 显示匹配一个或多个模式的文本行。时常会作为管道的第一步,以便对匹配的数据作进一步处理。
主要选项:
-E 使用扩展正则表达式进行匹配。grep -E 等于 egrep
-F 使用固定字符串进行匹配。grep -F 等于 fgrep
-e pat-list 通常,第一个非选项的参数会指定要匹配的模式,也可以提供多个模式,只要将他们放在引号里并以换行符分隔他们。模式以减号开头时,grep会混淆,将它视为选项。这就是-e选项派上用场的时候,可以指定其参数为模式——即使它以减号开头。
-f pat-file 从pat-file文件提取模式做匹配
-i 模式匹配时忽略字母大小写差异
-l 列出匹配模式的文件名称,而不是打印匹配的行
-q 静默的。如果模式匹配成功,则grep会成功的离开,而不将匹配的行写入标准输出;否则即是不成功。
-s 不显示错误信息。通常与-q 并用。
-v 显示不匹配模式的行。
行为模式 读取命令行上指明的每个文件,发现匹配查找模式的行时,将它显示出来。当指明多个文件时,grep会在每一行前面加上文件名与一个冒号。默认使用BRE(basic regular expression,基本的正则表达式)。
可以使用多个 -e -f选项,建立要查找的模式列表。
字符 | BRE/ERE | 模式含义 |
---|---|---|
\ | 两者都可 | 通常用来关闭后续字符的特殊意义,有时则是打开后续字符的特殊意义。如\(...\)与\{..\} |
. | 两者都可 | 匹配任何单个的字符,但NUl除外 |
* | 两者都可 | 匹配在他之前的任何数目(或没有)的单个字符。如.* 匹配任一字符的任意长度 |
^ | 两者都可 | 匹配紧接着的正则表达式,在行或字符串的起始处 |
$ | 两者都可 | 匹配前面的正则表达式,在字符串或行结尾处 |
[…] | 两个都可 | 方括号表达式,匹配方括号内的任一字符,^在方括号里的第一个字符则说明匹配不在方括号内的任何字符[^A-Z]:匹配不是大写的A-Z之间的字符 |
\{n,m\} |
BRE | 区间表达式,匹配在它前面的单个字符重现的次数区间。\{n\} 指的是重现n次,\{n,\} 为至少重现n次,\{n,m\} 为重现n-m次 |
\( \) |
BRE | 将(与)之间的模式存储在特殊的保留空间hoding space中,最多可存储9个独立的子模式,可通过转义序列\1到\9被重复用在相同模式里,例如(ab).*\1,指的是匹配于ab组合的两次重现,中间可能存在任何数目的字符。 |
\n | BRE | 重复在(和)括号内第n个子模式至此点的模式。n为1-9的数字,1为由左开始。 |
{n,m} | ERE | 和{n,m}一样 |
+ | ERE | 匹配前面正则表达式的一个或多个实例 |
? | ERE | 匹配前面正则表达式的0个或一个实例 |
| | ERE | 匹配于|符号前或后的正则表达式 |
() | ERE | 匹配括号括起来的正则表达式群 |
范例:
表达式 | 匹配 |
---|---|
tolstoy | 位于一行上任何位置的7个字母:tolstoy |
^tolstoy | 7个字母tolstoy,出现在行的开头 |
tolstoy$ | 7个字母tolstoy,出现在行的结尾 |
[Tt]olstoy | 在一行上的任意位居中,含有Tolstoy或tolstoy |
tol.toy | 含有tol加上任何一个字符,再接着toy这3个字母 |
tol.*toy | 在一行上的任意位置居中,含有tol这3个字母,加上任意的0或多个字符,再继续toy这3个字母,如toltoy,tolstoy,tolWHOtoy等 |
POSIX字符集:
类别 | 匹配字符 |
---|---|
[:alnum:] | 数字字符 |
[:alpha:] | 字母字符 |
[:blank:] | 空格space与定位tab字符 |
[:cntrl:] | 控制字符 |
[:digit:] | 数字字符 |
[:graph:] | 非空格字符 |
[:lower:] | 小写字母字符 |
[:print:] | 可显示的字符 |
[:punct:] | 标点符号字符 |
[:space:] | 空白字符 |
[:upper:] | 大写字母字符 |
[:xdigit:] | 十六进制数字 |
在方括号表达式中,所有其他的Meta字符都会失去其特殊含义。所以[*\.]匹配于字面上的星号,反斜杠以及句点。要让]进入该集合,可以将它放在列表的最前面:[]*\.]
,要让减号字符进入该集合,也要放到最前面[-*\.]
,]和-一起选择的话,]放到第一个,减号放到最后一个:[]*\.-]
后向引用:
\(ab\)\(cd\)[def]*\2\1
:adcdcdab,abcdeeecdab,abcdddeeffcdab,…
(why).*\1:一行里有两个why
在文本文件里进行替换
sed
一般来说,执行文本替换的正确程序应该是 sed ——流编辑器(Stream Editor),sed的设计就是用来以批处理的方式而不是交互的方式来编辑文件。当你知道要做好几个变更,比较简单的方式是将这些变更部分写到一个编辑中的脚本里,再将此脚本应用到所有必须修改的文件。
sed 's/:.*//' /etc/passwd | sort -u
:删除第一个冒号之后的所有东西,排序列表并删除重复部分。
cut
语法
cut -c list[file ...]
cut -f list[-d lelim][file...]
用途
从输入文件中选择一或多个字段或者一组字符,配合管道(pipeline),可再做进一步处理。
主要选项:
-c list
以字符为主,执行cut操作。list为字符编号或一段范围的列表(以逗点隔开),如1,3,5-12,42
-d delim 通过-f选项,使用delim作为定界符,默认为tab
-f list 以字段为主,坐剪下的操作。list为字段编号或一段范围内的列表,以逗号隔开。
$ ls -l | cut -c 1-10
使用join连接字段
语法 join [options ...] file1 file2
用途 以共同一个键值,将已存储文件内的记录加以结合。
选项:
-1 field1
-2 field2
-1 field1 是从file1中取出字段field1,-2 field2是从file2取出field2.字段编号自1开始,而非0.
-o file.field
输出file文件中的field字段。一般的字段则不打印。除非使用多个-o选项,即可显示多个输出字段。
-t separator:使用separator作为输入字段分隔字符,而非使用空白。此字符也为输出的字段分隔字符。
cat sales
#业务员数据
#业务员 量
joe 100
jane 200
herman 150
chris 300
cat quotas
#配额
#业务员 配额
joe 50
jane 75
herman 80
chris 95
# 为了让join得到正确结果,输入文件必须先完成排序。
merge-sales.sh
#!/bin/sh
# 删除注释并排序数据文件
sed @H_830_404@'/^#/d' quotas | sort > quotas.sorted
sed @H_830_404@'/^#/d' sales | sort > sales.sorted
#以第一个键值作结合,将结果产生至标准输出
join quotas.sorted sales.sorted
awk
awk @H_830_404@'program' [file ...]
awk程序基本架构为:
pattern {action}
...|awk @H_830_404@'{print some-stuff}'|...
例如:
awk @H_830_404@'{print $1}' 打印第一个字段(未指定pattern)
awk @H_830_404@'{print $2,$5}' 打印第2与第5个字段(未指定pattern)
awk @H_830_404@'{print $1,$NF}'打印第一个与最后一个字段,未指定pattern
awk @H_830_404@'NF > 0 {print $0}'打印非空行,指定pattern与action,$0表示整条记录
awk @H_830_404@'NF>0' 同上
awk -F: @H_830_404@'{print $1,$5}' /etc/passwd #处理/etc/passwd,以:作为分隔符
awk -F: @H_830_404@'{print "User",$1,"is really",$5}' /etc/passwd