使用 UNIX 进行文本处理( 三 )


在清单 7 中,您可以看到 sed 命令的基本格式 。模式是用来匹配输入(通常可以使用管道从另一个程序输入,或者重定向于文本文件)的正则表达式,替换是指插入某些文本并用其代替那些与模式相匹配的文本 。标志是用来控制替换行为的单个字符 。最常用的标志是 g(将替换应用于所有匹配模式的非重叠实例,而不仅仅是第一个匹配项) 。
实际上,模式和替换可以是各种各样的内容,并且它们之间不需要像在 tr 命令中那样具有 1:1 的关系 。
清单 7. sed 命令
sed -e s/pattern/replacement/flags
最简单的模式是一个或多个字符组成的字符串 。如清单 8 所示,例如将单词 one 替换为单词 another 。
清单 8. 最简单的正则表达式
chrish@dhcp3 [334]$ echo "Replace one Word" | sed -e s/one/another/
Replace another word
可以使用方括号将一个或多个字符括起来,以创建一个集合,该集合中的任何字符都可以匹配 。如清单 9 所示,让我们将所有的元音字母替换为下划线 。
清单 9. 匹配集合中的任何字符
chrish@dhcp3 [338]$ echo "This is a test" | sed -e s/[aeiouy]/_/g
Th_s _s _ t_st
请注意,示例中使用了 g 标志,以便将模式/替换应用于所有的匹配项,而不仅仅是第一个匹配项 。
sed 命令也可以理解 tr 命令所支持的那些命名字符类,POSIX 对这些字符类进行了定义,但是本文中的语法稍有不同 。清单 10 显示了如何替换任何空白字符(制表符、空格等等):
清单 10. 根据命名字符类匹配内容
chrish@dhcp3 [345]$ echo -e 'hellothere' 
hellothere
chrish@dhcp3 [346]$ echo -e 'hellothere' | sed -e 's/[[:space:]]/, /'
hello, there
echo 命令的 -e 标志用来告诉该命令扩展 C 风格的转义字符,在本示例中,它会把转换为制表符 。
您还可以使用“.(点号)匹配任何单个的字符 。如果您需要处理一些略有变化的数据,或者包含难以进行转义的特殊字符的数据,那么使用这个符号是非常方便的 。例如,在匹配引号时,我经常使用 .,所以我不需要在 Shell 中对引号进行转义 。清单 11 显示了一个正则表达式初学者在使用这个模式时出现的问题 。
清单 11. 这可能并不是想要的结果
chrish@dhcp3 [339]$ echo "This is a test" | sed -e s/./_/g
______________
既然您已经了解了这些非常基本的内容,下面介绍一些附加模式修饰符,要使用高级 正则表达式,您现在还可以使用 -E 选项代替 -e 。? 字符表示匹配前面模式元素的零个或一个实例,* 字符表示匹配前面元素的零个或多个实例 。字符表示匹配一个或多个前面的元素 。^ 字符匹配行首,而 $ 则匹配行尾 。清单 12 显示了实际应用中的情况 。
清单 12. 实际应用中的多个匹配项
chrish@dhcp3 [356]$ echo "hellooooo" | sed -E 's/o?$/_/g'
helloooo_
chrish@dhcp3 [357]$ echo "hellooooo" | sed -E 's/o*$/_/g'
hell_
chrish@dhcp3 [358]$ echo "hellooooo" | sed -E 's/o $/_/g'
hell_
如果使用圆括号将模式元素括起来,您可以在替换字符串中使用匹配的内容 。这些元素称为组,它们使得正则表达式搜索和替换操作的功能变得非常强大,但是却很难理解 。例如,在清单 13 中,您匹配一个或多个 l (el) 字符,并且后面跟着零个或多个 o 字符 。依次使用第二组和第一组中的内容对其进行替换,实际上是对它们进行交换 。请注意这个模式中各个组的引用方法,即反斜杠加上该组的序号 。
清单 13. 匹配组
chrish@dhcp3 [361]$ echo "hellooooo" | sed -E 's/(l )(o*)$/21/g'
heoooooll
通过在大括号中指定匹配的数目,您可以匹配特定数目的模式 。例如,模式 o{2} 将匹配两个(仅仅两个)o 字符 。

推荐阅读