'Perl one-liner substitution without further expansion of a shell variable?

I have a script to replace a specific email address in various files. The replacement address is the first parameter to the script:

#!/bin/bash
perl -pi -e s/'name\@domain\.org'/$1/ file-list

This doesn't work, as the @ character in $1 is substituted by perl. Is there a straightforward fix for this? Running the script as subst foo\@bar.com, subst foo\\@bar.com, subst "[email protected]", and so on, doesn't work. Is there a sed script that could handle this more easily?



Solution 1:[1]

Instead of expanding a shell variable directly in the perl code you can pass it as an argument by setting the s switch:

#!/usr/bin/env bash

perl -i -spe 's/name\@domain\.org/$replacement/' -- -replacement="$1" file1.txt file2.txt

In perl's s///, without the use of e or ee modifiers, variables in the replacement part are treated as literals so you don't need to escape them.

Solution 2:[2]

This works, but needs you to pass the new mail address to the script with the @ character preceded by \\:

#!/bin/bash
perl -pi -e "s/name\@domain.org/$1/" file-list

If the script is subst, run as:

subst newname\\@example.com

This is a better alternative, which uses sed to carry out the escaping:

#!/bin/bash
ADR="$(echo "$1" | sed -e 's/@/\\\@/')"
perl -pi -e "s/name\@domain.org/$ADR/" file-list

Of course, in this case it's probably better to use sed to do the whole thing.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2