3.5 添加标签

在RegExr中,取消勾选global但勾选multiline,点击Replace标签,然后在第一个文本框(在图3-4中标号为1)中输入:

  1. ^(.*)$

这会匹配第一行文本并将其捕捉。然后在下一个文本框(标号为2)中输入以下内容:

  1. <!DOCTYPE html>\n<html lang="en">\n<head><title>Rime</title></head>\n<body>\n
  2. <h1>$1</h1>

输入替换文本的时候,你会注意(标号为3的文本框中的)主题词文本在显示结果的文本框(标号为4)中变了,包含了你刚刚添加的标记(参见图3-4)。

enter image description here

图3-4 用RegExr添加标记

RegExr很好地展示了添加标记的一种方式,但它也有自己的局限性,比如说它不能将结果保存为文件。因此,我们不能把目光仅局限于浏览器。

3.5.1 使用sed添加标签

第2章我们已经看到了,在RegExr中能完成的工作,完全可以使用sed在命令行环境下做到。sed中的插入命令(i)允许你在文件或字符串中的某个位置之前插入文本。而与i命令相反的是命令a,它在某个位置之后添加文本(后面会用到a)。

以下命令从第1行开始插入HTML5的doctype(文档类型)和其他标记:

  1. sed '1 i\
  2. <!DOCTYPE html>\
  3. <html lang=\"en\">\
  4. <head>\
  5. <title>Rime</title>\
  6. </head>\
  7. <body>
  8. s/^/<h1>/
  9. s/$/<\/h1>/
  10. q' rime.txt

行尾的反斜杠(\)允许你在该流中插入新行而不会提前执行命令。引号前的反斜杠将引号转义为字面值。

正确运行这个sed命令会得到如下输出:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <title>The Rime of the Ancyent Mariner (1798)</title>
  5. </head>
  6. <body>
  7. <h1>THE RIME OF THE ANCYENT MARINERE, IN SEVEN PARTS.</h1>

以上sed命令保存在实例代码库中的top.sed文件中。用以下命令运行这些代码:

  1. sed -f top.sed rime.txt

可以得到与前面的命令相同的输出。要将输出保存到文件,则可以把输出重定位到一个文件中,比如:

  1. sed -f top.sed rime.txt > temp

除了会在屏幕上显示结果,重定位的那部分(>temp)还会将输出保存到文件temp中。

3.5.2 使用Perl添加标签

下面尝试用Perl完成同样的工作。先不解释,试一试这个:

  1. perl -ne 'print "<!DOCTYPE html>\
  2. <html lang=\"en\">\
  3. <head><title>Rime</title></head>\
  4. <body>\
  5. " if $. == 1;
  6. s/^/<h1>/;s/$/<\/h1>/m;print;exit;' rime.txt

与之前的sed命令比较一下。有哪些地方相似,哪些地方不同?sed命令稍微简单一些,但笔者认为Perl的功能强大很多。

以下是该命令的工作过程。

  • 变量$.表示当前行,使用if语句测试。如果if语句返回true(真),则当前行就是第1行。
  • 当Perl用if语句找到第1行时,它会打印文档类型(doctype)和几个HTML标签。和在sed中一样,这里也需要将引号转义。
  • 第一个替换操作在行起始位置插入

    标签,第二个替换操作在行尾处插入标签。第二个替换操作结尾处的m表示使用多行修饰符。这就保证了该命令会识别第一行的结尾。如果没有m,则$会匹配该文件的结尾。
  • 命令print打印替换结果。
  • 命令exit则会立即结束Perl程序。否则,因为有-n选项,它会循环执行文件的每一行;但这里不需要。

以上命令要键入很多内容。我将这些Perl代码放入名为top.pl的文件中,也可以在代码库中找到。

  1. #!/usr/bin/perl -n
  2. if ($ == 1) {
  3. print "<!DOCTYPE html>\
  4. <html lang=\"en\">\
  5. <head>\
  6. <title>The Rime of the Ancyent Mariner (1798)</title>\
  7. </head>\
  8. <body>\
  9. ";
  10. s/^/<h1>/;
  11. s/$/<\/h1>/m;
  12. print;
  13. exit;
  14. }

使用合集运行这个文件:

  1. perl top.pl rime.txt

得到的结果与前面是一样的,只是形式上稍有不同。(就像在sed中一样,你可以用>将输出重定位到文件中。)

下一章会涉及选择、分组和后向引用,还有其他一些概念。第4章见!