Perl是高端、通用、解释型、动态的编程语言家族。最初设计者拉里·沃尔为了让在UNIX上进行报表处理的工作变得更方便,决定开发一个通用的脚本语言,而在年12月18日发表。目前,Perl语言家族包含两个分支Perl5以及Perl6。虽然Perl不是正式的首字母缩略词,但仍有各种各样的逆向首字母缩略词,包括“实用的提取和报告语言”。
Perl借用了C、sed、awk、shell脚本、Lisp以及很多其他编程语言的特性。其中最重要的特性是Perl内部集成了正则表达式的功能,以及巨大的第三方代码库CPAN。
而这里的sed是什么呢?今天带大家了解一下。
sed(意为流编辑器,源自英语“streameditor”的缩写)是一个使用简单紧凑的编程语言来解析和转换文本Unix实用程序。
超实用性的Python零基础入门到进阶视频源码淘宝¥2购买已下架sed由贝尔实验室的LeeE.McMahon于年至年开发,并且现在大多数操作系统都可以使用。sed基于交互式编辑器ed(“editor”,)和早期qed(“quickeditor”,-66)的脚本功能。sed是最早支持正则表达式的工具之一,至今仍然用于文本处理,特别是用于替换命令。用于纯文本字符串操作和“流编辑”的常用工具还有AWK和Perl。
sed是为命令行处理数据文件而构建的早期Unix命令之一,首次出现在Version7Unix中。它很自然地演变成为流行的grep命令的后继。
最初的动机与grep(g/re/p)的替换类似,因此称为“g/re/s”。考虑到这样的话还会出现针对每个命令的专用程序,例如g/re/d,McMahon编写了一个通用的面向行的流编辑器,该编辑器后来成为了sed。sed的语法,特别是把/用于模式匹配,把s///用于替换,起源于sed的前身ed(当时ed很常用)而且正则表达式语法影响了其他一些语言,特别是ECMAScript和Perl。
后来,更强大的语言AWK问世,这些工具相互补充,让通过shell脚本完成强大的文本处理成为可能。sed和AWK常被认为Perl的祖先和灵感来源,并且影响了Perl的语法和语义,尤其影响了匹配和替换运算符。
sed是一个面向行的文本处理实用程序:它从输入流或文件中逐行读取文本到一个称为模式空间的内部缓冲区。每读一行开始一个循环。对于模式空间,sed会应用sed脚本指定的一个或多个操作。
sed实现了一种编程语言,其中包含大约25个指定文本操作的命令。对于每个输入行,在运行脚本之后,sed通常输出模式空间(由脚本修改的行),然后从下一行再次开始循环。
其他脚本结束行为可通过sed选项和脚本命令获得,例如d删除模式空间,q退出,N立即将下一行添加到模式空间,等等。因此,sed脚本对应于循环体,循环体遍历流的行,其中循环本身和循环变量(当前行号)是隐式的并由sed维护。
可以在命令行上指定sed脚本(-e选项),也可以从单独的文件中读取(-f选项)。sed脚本中的命令可以采用行号或正则表达式的作为地址。该地址确定决定命令何时运行。例如,2d将仅在第二个输入行上运行d(删除)命令(打印除第二个输入行之外的所有行),而/^/d将删除以空格开头的所有行。一些单独的特殊缓冲区,即保持空间,可以由几个sed命令使用,用于在循环之间保持和累积文本。
sed的命令语言只有两个变量(“保持空间”和“模式空间”)和类似GOTO的分支功能;然而,这种语言是图灵完备的,用深奥sed脚本甚至写得出推箱子、打砖块、国际象棋和俄罗斯方块等游戏。
为输入流的每一行执行一次主循环,在输入的每一行上计算sed脚本。sed脚本的每一行都是模式-动作对,指示着要匹配的模式和要执行的操作,可以将其重新组合为条件语句。因为主循环、工作变量(模式空间和保持空间)、输入和输出流以及默认操作(复制行到模式空间、打印模式空间)是隐式的,所以可以编写简洁的单行程序。例如,以下sed程序:
10q
将打印输入的前10行,然后停止。
用法
替换命令
下面的示例显示了sed用于替换的典型(也是最常见的)用法。这种用法确实是sed的最初动机:
seds/regexp/replacement/ginputFileNameoutputFileName
在某些版本的sed中,表达式的前面必须加上-e,以表示后面跟着一个表达式。s表示替换,而g表示全局,这意味着行中的所有匹配项都将被替换。要搜索的正则表达式(即pattern)放在第一个分隔符号(此处为斜杠)之后,而要替换成的字符串跟在第二个分隔符号后面。
斜杠(/)是传统的符号,起源于ed中的“搜索”字符,但其实在pattern和替换文本中都未出现的任何其他符号都可以用作分隔符号,使其可读性更强;这有助于避免“倾斜牙签综合征”。
替换命令源自ed中的搜索-替换,实现了简单的解析和模板化。regexp提供模式匹配和通过子表达式保存文本的功能,而replacement可以是纯文本,也可以是包含“完全匹配”,或第n个子表达式(从\1到\9)这种特殊转义序列的格式字符串。
例如,sed-rs/(cat
dog)s?/\1s/g用“cat”或“dog替换所有出现的“cats”或“dogs”,而不复制现有的“s”:在正则表达式中,(cat
dog)是第一个(也是唯一)保存的子表达式,格式字符串中的\1将其替换到输出里。
除了替换之外,使用大约25个sed命令可以进行其他形式的简单处理。例如,下面使用d命令删除空行或只包含空格的行:
sed/^*$/dinputFileName
本例使用了下列正则表达式元字符(sed支持所有正则表达式):
脱字符(^)匹配行首。
美元符号($)匹配行尾。
星号(*)匹配前一个字符零次或多次出现。
可以有很复杂的sed结构,让sed用作一种简单但高度专业化的编程语言。例如,可以通过使用标签(冒号后跟字符串)和分支指令b来管理控制流程。指令b后跟有效的标签名称,将把处理流程移动到该标签后面的块。
在Unix下,sed通常用作管道中的过滤器:
generateData
seds/x/y/g
也就是说,诸如“generateData”之类的程序生成数据,然后用sed把x替换成y。例如:
$echoxyzxyz
seds/x/y/g
yyzyyz
[notes1]
基于文件的sed脚本
将几个sed命令(每行一个命令)放入脚本文件(例如subst.sed)中然后使用-f选项从文件中运行命令(例如s/x/y/g)通常很有用:
sed-fsubst.sedinputFileNameoutputFileName
可以在脚本文件中放置任意数量的命令,使用脚本文件也可以避免shell转义或替换的问题。
这样的脚本文件可以直接从命令行执行,方法是在其前面加上一个包含sed命令的shebang行,并为该文件分配可执行权限。例如,可以使用以下内容创建文件subst.sed:
#!/bin/sed-f
s/x/y/g
然后,当前用户可以使用chmod命令使文件可执行:
chmodu+xsubst.sed
然后可以直接从命令行执行该文件:
subst.sedinputFileNameoutputFileName
GNUsed中引入的-i选项允许就地编辑文件(实际上,在后台创建了一个临时输出文件,然后将原始文件替换为临时文件)。
例如:
sed-is/abc/def/fileName
示例
Hello,world!例子
#convertinputtextstreamtoHello,world!
s/.*/Hello,world!/
q
sed是独一无二的,典型的sed程序相当简短。
sed脚本可以有注释(以#符号开头的行)。
s(替换)命令是最重要的sed命令。
sed允许使用q(退出)等命令进行简单编程。
sed使用正则表达式,例如.*(任何字符的零个或多个)。
限制和替代方案
虽然sed具有简单性和局限性,但对于大量用途而言,它的功能已经足够强大。对于更复杂的处理,可以使用更强大的语言,如AWK或Perl或者PowerShell。
虽然使用保持缓冲区理论上可以进行任意复杂的转换,但如果转换行的方式比正则表达式提取和模板替换更复杂,则使用一般会使用上面提到的更强大的语言。
相反,对于更简单的操作,grep(打印匹配模式的行),head(打印文件的第一部分),tail(打印文件的最后部分)和tr(翻译或删除字符)等专门的Unix实用程序通常更可取。对于设计用于执行的特定任务,此类专用实用程序通常比较一般的解决方案(如sed)更简单、清晰和快速。
ed/sed命令和语法继续用于派生程序,例如文本编辑器vi和vim。sam/ssam与ed/sed类似,其中sam是Plan9编辑器,ssam是它的流接口,其功能类似于sed。