【问题标题】:Replacing single line of text with multiple lines of HTML using Perl使用 Perl 将单行文本替换为多行 HTML
【发布时间】:2014-12-08 17:59:15
【问题描述】:

我在 bash 脚本中使用以下内容将字符串替换为文件的内容:

readonly changes=`cat changes.txt`
perl -pi -e 's/\${changesMarker}/'"$changes"'/g' changelog_template.html

文件“changes.txt”包含几行 HTML。没什么特别的,只是一个无序列表,包括

    打开和关闭标签以及
  • 标签。

    Perl 不断告诉我:

    Illegal division by zero at -e line 1, <> line 1.
    

    我猜 Perl 正在尝试评估替换文本?我该如何解决这个问题?

    文件changelog_template.html是这样的:

    <html>
    <body>
        What's changed:
        ${changesMarker}
    </body>
    </html>
    

    文件 changes.txt 是这样的:

    <ul>
    <li>Fixed unicode error</li>
    </ul>
    

【问题讨论】:

  • 您使用 bash 脚本只是为了将文件的内容读入 shell 变量。为什么不将所有代码都放在 Perl 脚本中,而不必为了规避插值之类的事情而费尽心思?
  • 试试这个“s/${changes}/$changes/g”
  • 您还应该提供一些示例输入和输出。现在看起来您正在尝试将字符串${changeMarker}(或一些未在任何地方初始化的同名变量)更改为文件中包含的任何内容,并用单引号和双引号括起来。至少可以说是非常奇怪和令人困惑的。或者,出于某种原因,您正试图用自己替换相同的字符串。所以,请澄清你的意图。
  • @SteveMcLeod 这无关紧要。将所有代码封装在一个脚本中仍然更容易。然后,您可以根据需要在 bash 脚本中使用该脚本:perl script.pl build/changes.txt changelog_template.html
  • 让我举一个例子来说明这个任务带来的困难。如果您的“标记”包含正则表达式元字符、斜杠或美元符号怎么办? Shell 将首先尝试对它进行插值,然后是 Perl,然后您将面临一项噩梦般的任务,该任务很容易出现错误并且非常难以维护。

标签: bash perl


【解决方案1】:

有了确切的文本,这可能会使用您的解决方案来解决。但是,如果您的文本发生更改,我不建议使用它。假设单引号可以防止 shell 插值,你可以这样做:

readonly changes=`cat changes.txt`
perl -pi -e 's/\${changesMarker}/$ENV{changes}/g' changelog_template.html

从技术上讲,您可以将其替换为:

perl -0777 -pie 'BEGIN { local @ARGV = shift; $changes = <>; }
           s/\${changesMarker}/$changes/g;' changes.txt changelog_template.html

这会破坏文件,这更好,因为它允许多行匹配(理论上)。

这是一个足够简单的 Perl 脚本:

use strict;
use warnings;

undef $/;
open my $in, "<", shift or die "Cannot open input file: $!";
my $changes = <$in>;

while (<>) {
    s/\${changesMarker}/$changes/g;
    print;
}

这样使用:

perl -pi script.pl changes.txt changelog_template.html

【讨论】:

  • 字符串${changesMarker} 不包含换行符,因此-0777 不会产生影响。
  • @ikegami 这肯定会产生重大影响。这就是我们如何 slurp 输入文件。即使在这种特殊情况下没有严格要求,通常在这种情况下也更好。
  • 我知道它的作用。更好?!?
【解决方案2】:

您将字符串转换为 shell 文字,但您未能先将其转换为 Perl 代码。

例如,如果$changes 的内容是&lt;b&gt;foo&lt;/b&gt;,则结束将以下程序传递给 Perl:

s/\${changesMarker}/<b>foo</b>/g
                           ^
                           |
               Ends the substitution operator

我的建议是避免生成 Perl 代码。将字符串作为参数传递

perl -i -pe'
   BEGIN { $replacement = shift(@ARGV) }
   s/\${changesMarker}/$replacement/g
' "$change" changelog_template.html

或者作为环境变量。

REPLACEMENT="$changes" \
   perl -i -pe's/\${changesMarker}/$ENV{REPLACEMENT}/g' \
      changelog_template.html

【讨论】:

  • @TLP,其实你可以。但就像你说的,在这里这样做是错误的。我在想什么?固定。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-29
  • 2012-02-08
  • 2023-03-23
  • 1970-01-01
  • 2010-11-05
  • 2017-04-30
相关资源
最近更新 更多