Shell工具中正则表达式技术
awk, sed和egrep是Unix中文本处理相关的Shell工具。awk采用了DFA匹配引擎。egrep依据说使用的功能在DFA和NFA引擎之间进行切换(实现了两中引擎)。sed采用传统的NFA匹配引擎。如果想进一步了解传统的NFA引擎背后的规则,请看“正则表达式和模式匹配”一节。
本章涵盖GNU egrep 2.4.2,一个文本行搜索程序;GNU sed 3.2,一个脚本编辑命令工具;和GNU awk 3.1,一种文本处理语言。
支持的元字符
awk, sed和egrep支持表61到表65中列出来的元字符和元序列。关于每一个元字符的详述,请看“正则表达式元字符、模式和结构”一节。
Shell字符表示 | ||
序列名 | 序列描述 | 支持工具 |
/a | 告警(bell) | awk, sed |
/b | 空格,只有在字符类中有效 | awk, |
/f | 分页 | awk, sed |
/n | 换行 | awk, sed |
/r | 回车 | awk, sed |
/t | 水平制表符 | awk, sed |
/v | 垂直制表符 | awk, sed |
/ooctal | 通过1、2或3个八进制码数指定的字符 | sed |
/octal | 通过1、2或3个八进制码数指定的字符 | awk |
/xhex | 通过1个或2个十六进制数指定的字符 | awk, sed |
/x{hex} | 通过十六进制码指定的字符 | awk, sed |
/ddecimal | 通过1个或2个十进制数指定的字符 | awk, sed |
/cchar | 命名的控制字符 | sed |
/b | 空格 | awk |
/matecharacter | 转义元字符,所以它仅表示自身 | awk, sed, egrep |
表61 Shell字符表示
Shell字符类和类似(class-like)结构 | ||
字符类 | 类描述 | 支持工具 |
[…] | 列出来的或包含在列表范围的单一字符 | awk, sed, egrep |
[^…] | 不在列出来的或不包含在列表范围的单一字符 | awk, sed, egrep |
. | 除换行之外的任意字符 | awk, sed, egrep |
/w | 字字符,[a-zA-Z0-9_] | egrep, sed |
/W | 非字字符, [^a-zA-Z0-9_] | egrep, sed |
[:prop:] | 匹配POSIX字符集内的任意字符 | awk, sed |
[^[:prop:]] | 匹配不在POSIX字符集内的任意字符 | awk, sed |
表62 Shell字符类和类似(class-like)结构
Shell锚和其他0宽测试 | ||
序列名 | 序列描述 | 支持工具 |
^ | 匹配字符串的开头,即时有内切的换行 | awk, sed, egrep |
$ | 匹配字符串末尾,即时有内切的换行 | awk, sed, egrep |
/< | 匹配字边界的起始位置 | egrep |
/> | 匹配字边界的末尾 | egrep |
表63 Shell锚和其他0宽测试
Shell注释和模式转换器 | ||
模式名 | 模式描述 | 支持工具 |
flag:i或I | ASCII字符大小写不敏感匹配 | sed |
命令行选项:-i | ASCII字符大小写不敏感匹配 | egrep |
set IGNORECASE为非0(none-zero) | Unicode字符大小写不敏感匹配 | awk |
表64 hell注释和模式转换器
Shell归组、捕获、条件和控制 | ||
序列 | 序列描述 | 支持工具 |
(PATTERN) | 归组 | awk |
(PATTERN/) | 组和捕获字匹配,填写/1,/2,...,/9 | sed |
/n | 包含第n个被捕获子匹配 | sed |
...|... | 替换;匹配一个或其他 | awk, sed, egrep |
贪婪计量器 | ||
* | 匹配0或多次 | awk, sed, egrep |
+ | 匹配1次或多次 | awk, sed, egrep |
? | 匹配1次或0次 | awk, sed, egrep |
/{n/} | 匹配精确的n次 | sed, egrep |
/{n,/} | 至少匹配n次 | sed, egrep |
/{x,y/} | 至少匹配x次,最多y次 | sed, egrep |
表65 Shell归组、捕获、条件和控制
egrep
grep [options] pattern files
grep在文件搜索pattern发生的位置,并打印出每一个匹配的行。
实例
grep实例 |
$ echo 'Spiderman Menaces City!' > dailybugle.txt $ egrep -i 'spider[- ]?man' dailybugle.txt Spiderman Menaces City! |
sed
sed '[address1][,address2]s/pattern/replacement/[flags]' files
sed -f script files
默认的情况下sed把替换应用于files中的每一行。每一个address既可以是一个行号,也可以是一个正则表达式。当在正则表达式中使用时,必须在双方斜杆之内定义(/.../)。
如果指定了address1,那么替换从指定的行开始,或者第一个匹配的行,到文件末尾为止,或由address2指定或匹配的行。&和/n将在replacement中作为匹配结果被解释。
&被pattern匹配的文本替换。/n与当前匹配中捕获组(1...9)有关。以下是可用的标识:
n 替换一行内第n个匹配,n在1到512之间。
g 替换一行中所发生的所有pattern。
p 打印所有成功替换的行。
w file 把成功的替换写到文件中。
实例
把时间格式从MM/DD/YYYY 改为DD.MM.YYYY |
$ echo 12/30/1969' | sed 's!/([0-9][0-9]/)//([0-9][0-9]/)//([0-9]/{2,4/}/)! /2./1./3!g' |
awk
awk 'instruction' files
awk –f script files
包含在instruction或 script中脚本必须由一系列的/pattern/ {action}对组成。action码应用于被pattern的每一行。awk还为模式匹配提供了一些函数。
函数
match(text, pattern)
如果pattern匹配text,返回text中匹配的起始位置。一个成功的匹配还设置变量RSTART的值为匹配起始位置,设置变量RLENGTH的值为匹配中字符的个数。
gsub(pattern, replacement, text)
用replacement来替换text中每一个pattern匹配,并返回替换的次数。如果没有指定text则默认为$0。
sub(pattern, replacement, text)
用replacement来替换text中第一个pattern匹配,并返回替换的次数。一个成功的替换返回1,一个不成功的替换返回0。如果没有指定text则默认为$0。
实例
创建一个awk文件,并通过命令行执行这个文件 |
$ cat sub.awk { gsub(/https?:[a-z_.//w#~:?+=&;%@!-]*/, "<a href=/"/&/">/&</a>"); } $ echo "Check the web site, http://www.oreilly.com/ catalog/repr" | awk -f sub.awk |