Trying to search and replace password variables with special characters in multiple files with a perl
command in a bash script. So far I have:
grep -rlF "${old_pass}" | xargs perl -p -e "s~\Q$old_pass~\E$new_pass~g"
and it works for most cases, however sometimes it fails. For example, given old_pass=*DGB9Twq7WTwz@wR
and new_pass=tDx6U&ShRv}E3Mdb
the above command results in tDx6U&ShRv}E3Mdb@wR
instead of just tDx6U&ShRv}E3Mdb
.
Please note that passwords are generated automatically and can consist of all uppercase and lowercase letters, numbers and all special characters. So the working version must be able to take into account (escape) all kind of possible password versions.
You tried and failed to generate the correct Perl code. But the real problem is that you tried to generate Perl code form the shell in the first place. There are three primary ways of passing information to Perl without using STDIN or external storage.
Arguments
perl -pe'BEGIN { ($o,$n)=splice(@ARGV,0,2) } s/\Q$o/$n/g' -- "$old_pass" "$new_pass"
Command-line options
In a full program, you'd use Getopt::Long, but perl -s
will do fine here.
perl -spe's/\Q$o/$n/g' -- -o="$old_pass" -n="$new_pass" --
Environment variables
O="$old_pass" N="$new_pass" perl -pe's/\Q$ENV{O}/$ENV{N}/g' --
(In your case, you'd have to set the env vars for xargs
instead of perl
itself.)
By the way, you should further restrict what your regex pattern matches. As it stands, you could have false positives. (Matching the wrong user's password. matching part of a password. Matching something that isn't a password at all.)