0

I want to replace some strings in files that contain $ signs with an other string that also contains $ signs plus the value from a bash variable. The file contains strings like the following.

$Rev: 12345 $ $Author: 12345 $

Lets say I have a bash variable called i containing the string foo. I now want to replace $Rev: 12345 $ with $Rev: $i $. I tried using sed but since sed doesn't support non-greedy regex I switched to perl. Perl works fine when I don't use any bash variables.

# cat file
$Rev: 12345 $ $Author: 12345 $
# perl -p -i -e 's;\$Rev:.*?\$;\$Rev: test \$;g' file
# cat file
$Rev: test $ $Author: 12345 $

But no matter how I escape the $ signs in the command, I cannot get it to work with a bash variable.

# cat file
$Rev: 12345 $ $Author: 12345 $
# i="foo"
# echo $i
foo
# perl -p -i -e "s;\$Rev:.*?\$;\$Rev: $i \$;g" file
Final $ should be \$ or $name at -e line 1, within string
syntax error at -e line 1, near "s;$Rev:.*?$;$Rev: foo $;g"
Execution of -e aborted due to compilation errors.
# perl -p -i -e "s;\\$Rev:.*?\\$;\$Rev: $i \\$;g" file
# cat file
$Rev: foo $ $Author: foo $

Thanks for your help!

3
  • These auto-updated version comments were thought to be a good idea back in the RCS and CSV days, but experience taught us that they were not. Commented Sep 29, 2022 at 13:04
  • Use single quotes around Perl scripts in Bash. Commented Sep 29, 2022 at 13:05
  • Why do you set a bash variable to use as replacement in Perl code? Do you just not know how to set variables in Perl? Or is this a variable that will be used in other code? Commented Sep 29, 2022 at 15:11

2 Answers 2

4

It's better to use a Perl variable inside Perl, not let the shell expand its variable into Perl code.

perl -i~ -pe 's/^\$Rev:.*?\$/\$Rev: $i \$/g' -s -- -i="$i" file

You can then use single quotes around the code which makes it much easier to backslash stuff correctly.

The -s tells Perl to accept -var=val switches and set Perl variable $var to val before running the code.

Sign up to request clarification or add additional context in comments.

4 Comments

I like this better than my suggestion.
This is in fact a cleaner solution but it will also output the replaced string. I could rederict the output to /dev/null like so "perl -pe 's;\$Rev:.*?\$;\$Rev: $i \$;g' -s -- -i="$i" file> /dev/null 2>&1" but that seems unnecessarily complicated compared to @JimDavis solution. It propably doesn't matter which one I use. What do you think?
@Chullian What do you mean "it will output the replaced string"? Are you talking about the fact that choroba left out the -i (in-place edit) switch?
@Chullian: Updated to include the -i.
0

Try putting $i outside the quotes entirely:

perl -pi -e 's;\$Rev:.*?\$;\$Rev: '$i' \$;g' file
#           ^---------------------^  ^-----^

Or, you could export the variable to sub-processes, and access it via the %ENV hash in Perl:

export i="foo"
perl -pi -e 's;\$Rev:.*?\$;\$Rev: $ENV{i} \$;g' file

Comments

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.