文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>正则表达式之sed

正则表达式之sed

时间:2008-09-23  来源:落魄剑客

sed 是流编辑器 (stream editor) 的简写。文本编辑器的传统、现代定义是可用于创建和编辑文本文件的交互式应用程序。sed 也是一个文本编辑器,但它是一个命令行实用程序而不是交互式实用程序,从而使之成为一个极其强大的批处理编辑工具。sed 通常在 UNIX Shell 脚本中用于过滤较大的文本文件集。在本教程的第一部分中,您使用了一个讨论 golf 的小型测试文件。为了演示 sed 编辑器的高级功能,您将使用一个很小的代码片段,开发人员可能希望在批处理过程中更改该代码片段。

请将以下文本复制并粘贴到一个名为 sed.txt 的文件中:

system "echo 'project:$project' >> logfile"; system "echo 'version:$version' >> logfile"; system "echo 'optionalid:$optionalid' >> logfile"; system "echo 'nodes:$nodes' >> logfile"; system "echo 'threads:$threads' >> logfile"; 

正斜杠

前面解释过的用于 grep 的所有特殊字符在 sed 中也有效。然而,若要使用 sed,您必须了解一些附加语法。sed 中的基本表达式由四个部分组成,各个部分之间用正斜杠 (/) 分隔。以下是用于基本 sed 命令的常见语法:

sed s/REGULAREXPRESSION/REPLACEMENTSTRING/flags INPUT_FILE

s——搜索和替换

s 指示您希望执行搜索和替换。正斜杠用于绑定 sed 中的正则表达式。例如,如果您只希望将词条 logfile 替换为 logfile.txt,则可以运行以下命令:

sed s/logfile/logfile.txt/ sed.txt

输出应该类似如下:

system "echo 'project:$project' >> logfile.txt"; system "echo 'version:$version' >> logfile.txt"; system "echo 'optionalid:$optionalid' >> logfile.txt"; system "echo 'nodes:$nodes' >> logfile.txt"; system "echo 'threads:$threads' >> logfile.txt"; 

在此情况下要注意的一个要点在于,sed 不会实际更改 sed.txt 的内容。相反,它将输出发送到标准输出设备。对于这些示例,您将把输出发送到标准输出设备,以便能够立即看到操作结果。

为便于将来参考,可以捕获输出或将其发送到某个新文件。例如,若要将输出发送到 sed_new.txt,可以运行以下命令:

sed s/logfile/logfile.txt/ sed.txt > sed_new.txt

反斜杠

在学习使用斜杠的同时,还有另一个非常重要的特殊字符需要学习。反斜杠 (\) 称为转义字符,因为它对正则表达式解释中的下一个字符进行转义。更简单的是,将一个反斜杠放在特殊字符前,将使该字符成为普通项而不是命令项。这非常重要,因为许多文件(尤其是在编写代码的时候)广泛利用了与用于执行正则表达式的字符相同的字符。在您的 sed.txt 文件中,您会注意到美元符号的使用。如果您希望替换 $project 而不替换 project,则需要在搜索和替换中使用转义字符:

sed s/\$project/\$project_name/ sed.txt

您可以在输出中看到 $project 被更改了,但是 project 没有被更改。

system "echo 'project:$project_name' >> logfile"; system "echo 'version:$version' >> logfile"; system "echo 'optionalid:$optionalid' >> logfile"; system "echo 'nodes:$nodes' >> logfile"; system "echo 'threads:$threads' >> logfile"; 

更改某个项的多个实例

这引入了 sed 中的另一个重要功能。如果您希望同时更改 project 的两个实例,该怎么办呢?通过到目前为止已学到的知识,合理的回答是只需使用 project 作为正则表达式,但是此回答并不是非常正确。下面将继续并进行尝试,以便能够演示和解释该过程:

sed s/project/project_name/ sed.txt

在输出中可以看到,project 的第一个实例被更改为 project_name:

system "echo 'project_name:$project' >> logfile"; system "echo 'version:$version' >> logfile"; system "echo 'optionalid:$optionalid' >> logfile"; system "echo 'nodes:$nodes' >> logfile"; system "echo 'threads:$threads' >> logfile"; 

然而,第二个实例未更改,尽管它肯定匹配您的正则表达式。您从第一个示例中知道,sed 似乎更改其输入中的每个匹配字符串,而不是仅更改第一个匹配字符串,因为它更改 logfile 的每个实例。

区别在于,logfile 的每个实例在单独的行上,而同一行上却有两个 project 实例。这为什么非常重要?因为 sed 被实现为一个行编辑器。它一次将一个单独的行放到内存中,并将其作为单个单元来操作。在运行 sed 时务必记住这点,因为所有命令行选项都是按这个设计原则来设计的(从而使大多数 sed 实现不会受到与系统内存有关的文件大小限制)。缺省情况下,每一行都视为 sed 命令的一次新的执行。尽管在第一个示例中似乎不是这样,但是其中 sed 命令仅替换匹配字符串的第一个实例。然而,您可以简单地使用一个 g 标志来改变此行为。

g 标志

执行同样的 sed 命令,但这次在结尾附加一个 g:

sed s/project/project_name/g sed.txt

这次,第一行上的两个 project 实例都被更改为 project_name:

system "echo 'project_name:$project_name' >> logfile"; system "echo 'version:$version' >> logfile"; system "echo 'optionalid:$optionalid' >> logfile"; system "echo 'nodes:$nodes' >> logfile"; system "echo 'threads:$threads' >> logfile"; 

您可能记得,g 是 global 的简写。

运行初步的搜索

sed 的另一个强大功能是在搜索和替换操作前运行初步搜索,以确定当前是否在您希望执行命令的行上。这差不多类似于在 sed 中执行 grep。在您的例子中,您可能希望更改 node 变量的日志文件,而不是将它与所有其他输出分组在一起。为此,您需要将字符串 logfile 更改为 logfile_nodes,但是仅在属于节点的行上执行更改。以下命令可以确切完成此任务:

sed /nodes/s/logfile/logfile_nodes/ sed.txt

下面是其输出:

system "echo 'project:$project' >> logfile"; system "echo 'version:$version' >> logfile"; system "echo 'optionalid:$optionalid' >> logfile"; system "echo 'nodes:$nodes' >> logfile_nodes"; system "echo 'threads:$threads' >> logfile"; 

更改以冒号结尾的每个字符串

现在,尝试使用一些您在使用 grep 时学习到的正则表达式知识,不过这次是在 sed 命令中使用。通过在 sed 中使用以下正则表达式,您可以更改以冒号结尾的每个字符串:

sed s/[a-z]*:/value:/g sed.txt

输出应该类似如下:

system "echo 'value:$project' >> logfile"; system "echo 'value:$version' >> logfile"; system "echo 'value:$optionalid' >> logfile"; system "echo 'value:$nodes' >> logfile"; system "echo 'value:$threads' >> logfile"; 

这相当酷,但不是非常合理。它不是非常合理的原因在于,您的所有变量前都有单词 value,没有办法对各个变量进行区分。然而,通过使用 sed 的另一个功能,您可以使这转变为一个实际的示例。

“和”号

“和”号 (&) 表示与您的正则表达式匹配的字符串。换句话说,如果 [a-z]*: 在某个特定行上被证明为 project:,则“和”号将包含该值。这会非常有用。看一下以下这个示例:

sed s/[a-z]*:/new_\&/g sed.txt

这次,您修改了每个匹配字符串,但是保留了与每个变量关联的标识符:

system "echo 'new_project:$project' >> logfile"; system "echo 'new_version:$version' >> logfile"; system "echo 'new_optionalid:$optionalid' >> logfile"; system "echo 'new_nodes:$nodes' >> logfile"; system "echo 'new_threads:$threads' >> logfile"; 

执行多个命令序列

使用 sed,您还可以一次做多件事情。若要一次执行多个命令序列,您必须在每个表达式前使用 -e 标志。缺省情况下,sed 将第一个参数解释为一个表达式,但是在运行多个命令时,您需要作出更明确的指定,因此要使用 -e 标志。例如:

sed -e s/[a-z]*:/value:/g -e s/logfile/name/g sed.txt

可以在此例中看到,sed 在适当位置插入了 value: 和 name:

system "echo 'value:$project' >> name"; system "echo 'value:$version' >> name"; system "echo 'value:$optionalid' >> name"; system "echo 'value:$nodes' >> name"; system "echo 'value:$threads' >> name"; 

正如您开始看到的,在大规模批处理过程中,sed 可以是个非常强大的文件编辑工具。在前一示例中,您是在对单个文件进行操作,就像在使用 grep 时所做的那样。不要忘了,这些实用程序的部分强大功能在于跨多个文件运行它们,这可以使用通配符或文件列表替换单个文件来实现,您已在本教程中这样使用过了。

相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载