0

I'm using the following in a bash script to replace a string with the contents of a file:

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

The file "changes.txt" contains a few lines of HTML. Nothing extraordinary, just an unordered list, including the <UL> open and closing tags and the <LI> tags.

Perl keeps telling me:

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

I guess Perl is trying to evaluate the replace text? How do I fix this?

The file changelog_template.html is something like this:

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

The file changes.txt is something like this:

<ul>
<li>Fixed unicode error</li>
</ul>
6
  • 2
    You are using a bash script only to read the content of a file into a shell variable. Why not put all the code in the Perl script and not have to jump through a lot of hoops trying to circumvent interpolation and whatnot? Commented Dec 8, 2014 at 18:05
  • try this "s/${changes}/$changes/g" Commented Dec 8, 2014 at 18:05
  • 1
    You should also give some sample input and output. Right now it looks like you are trying to change the string ${changeMarker} (or some variable with the same name which is not initialized anywhere) into whatever is contained in the file, surrounded by both single and double quotes. Which to say the least is very strange and confusing. Or you are trying to replace the same string with itself, for some reason. So, clarify your intent please. Commented Dec 8, 2014 at 18:08
  • 1
    @SteveMcLeod That is irrelevant. It is still easier to encapsulate all of the code in a single script. You can then use that script in your bash script if you like: perl script.pl build/changes.txt changelog_template.html Commented Dec 8, 2014 at 18:10
  • 1
    Let me give you an example of the difficulties this task presents. What if your "marker" contains regex meta characters, or slashes, or dollar signs? The shell will first try to interpolate this, then Perl, and you are left with a nightmarish task which will be prone to bugs and really difficult to maintain. Commented Dec 8, 2014 at 18:13

2 Answers 2

2

With that exact text this might be solved using your solution. However, I would not recommend using it if your text changes. Assuming the single quotes prevents shell interpolation, you can get away with doing this:

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

Technically, you can replace this with:

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

Which will slurp the file, which is better since it allows multiline matches (theoretically).

This is a simple enough Perl script:

use strict;
use warnings;

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

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

Used like this:

perl -pi script.pl changes.txt changelog_template.html
Sign up to request clarification or add additional context in comments.

3 Comments

The string ${changesMarker} contains no newlines, so -0777 won't make a difference.
@ikegami It will certainly make a crucial difference. That's how we slurp the input file. And it is generally speaking better in this type of case, even if not strictly required in this particular case.
I know what it does. Better?!?
2

You converted the string into a shell literal, but you failed to convert it into Perl code first.

For example, If the content of $changes was <b>foo</b>, you end passing the following program to Perl:

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

My recommendation is to avoid generating Perl code. Either pass the string as an argument

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

Or as an environment variable.

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

1 Comment

@TLP, Actually, you can. But like you said, it's wrong to do so here. What was I thinking? Fixed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.