I have been trying to replace some text in a .txt file using a shell script and perl.
oldKey=123
trimmedNewKey=456
#Export shell variables, so that they can be used by perl
export oldKey
export trimmedNewKey
#Search and Replace
perl -pi -e 's/$ENV{oldKey}/$ENV{trimmedNewKey}/g' AppConstants.txt
This fails, but on the other hand, if I use string directly for the search param, it works:
perl -pi -e 's/123/$ENV{trimmedNewKey}/g' AppConstants.txt.
I am not a shell guy and can't figure out why my "search" param can't be evaluated via a variable. Help !
Try changing your code into
oldKey=123
trimmedNewKey=456
perl -pi -e "s/$oldKey/$trimmedNewKey/g" AppConstants.txt
This should work, because in a string enclosed in single quotes, there is no variable and wildcard expansion, as it is the case in a string enclosed in double quotes.
It is possible perhaps to pass some variables to perl so that the expansion happens inside the perl program, but why to make it complex when you can solve it in an easier way?
Related
Let's say 'pm.max_children = 8' on the file '/usr/local/etc/php-fpm.d/www.conf'
The result of the following is supposed to be 40 but $1 is just ignored.
aaa=5
perl -i.bak -e "s/pm.max_children\s*=\s*\K([0-9]+)/($1 * $aaa)/ge" /usr/local/etc/php-fpm.d/www.conf
But the strange thing is the following is working, in case $aaa is not a variable.
perl -i.bak -e "s/pm.max_children\s*=\s*\K([0-9]+)/($1 * 3)/ge" /usr/local/etc/php-fpm.d/www.conf
The meaning of $1 is different in the shell and in Perl.
In the shell, it means the first positional argument. As double quotes expand variables, $1 in double quotes also means the first positional argument.
In Perl, $1 means the first capture group matched by a regular expression.
But, if you use $1 in double quotes on the shell level, Perl never sees it: the shell expands $1 as the first positional argument and sends the expanded string to Perl.
You can use the %ENV hash in Perl to refer to environment variables:
aaa=5 perl -i.bak -pe 's/pm.max_children\s*=\s*\K([0-9]+)/($1 * $ENV{aaa})/ge' /usr/local/etc/php-fpm.d/www.conf
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 "foo#bar.com", and so on, doesn't work. Is there a sed script that could handle this more easily?
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.
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.
I'm trying to hash a password using the crypt hash function in Perl. In a Bash script so far I have:
password='Pa$$word'
hashedPassword="$(perl -e "print crypt('$password', 'salt'), \"\n"")"
I then modify/copy /etc/shadow using sed:
sed -e '/^user1:/s_:[^:]*:_:'"$hashedPassword"':_' /etc/shadow > /tmp/shadow
The method works, except when passing a string containing single quotes. How can I handle a password containing ' single quotes? Running Solaris 10 OS.
Your problem is in bash. Trying to set a shell variable containing a single quote by enclosing it in single quotes will not work. Per the man page:
Enclosing characters in single quotes preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash.
Supply the password as a parameter to your one-liner instead of interpolating it directly in the code:
#!/usr/bin/env bash
password='Pa$$word'
hashedPassword=$(perl -e 'print crypt($ARGV[0], "salt"), "\n"' $password)
echo "p='$password', h='$hashedPassword'"
Output:
p='Pa$$word', h='saFQXTeqbkiIQ'
As password contains $ and $ are syntactical in perl it is not easy to pass in hard in script, other options are to pass by arguments or by environment.
# by argument
perl -e '($password, $salt)=#ARGV;print crypt($password, $salt), "\n"' "$password" "$salt"
# by environment variable
password=$password salt=$salt perl -e 'print crypt($ENV{password}, $ENV{salt}), "\n"'
I am writing a shell script to replace a variable content which is an integer with another, using perl in a shell script.
#!/bin/sh
InitialFileStep="$1"
CurrentStage=$((($i*(9*4000))+$InitialFileStep))
PreviousStage=$((($(($(($i-1))*(9*4000)))) + (InitialFileStep)))
perl -pi -e 's/$PreviousStage/$CurrentStage/g' file.txt
echo "Hey!"
It seems it cannot find the variable content in the file.
I don't know what is the problem, is it the because the variables are integers and not strings?
The shell does not interpret anything inside single quote. '$ThisIsASimpleStringForTheShell' so try:
perl -pi -e 's/'"$PreviousStage"'/'"$CurrentStage"'/g' file.txt
The double quotes prevents possible spaces to mess up your command.
Mixing single and double quotes gives you the possibility to add regex operator to your command, preventing shell to interpret them before perl. This command substitute the contents of $PreviousStage with the contents of $CurrentStage only if the former is alone in a single line:
perl -pi -e 's/^'"$PreviousStage"'$/'"$CurrentStage"'/g' file.txt
The variables only exist in your shell script; you can't directly use them in your Perl script.
I hate attempting to generate Perl code from the shell as the previous solutions suggest. That way madness lies (though it works here since you're just dealing with integers). Instead, pass the values as arguments or some other way.
perl -i -pe'BEGIN { $S = shift; $R = shift; } s/\Q$S/$R/g' \
"$PreviousStage" "$CurrentStage" file.txt
or
export PreviousStage
export CurrentStage
perl -i -pe's/\Q$ENV{PreviousStage}/$ENV{CurrentStage}/g' file.txt
or
S="$PreviousStage" R="$CurrentStage" perl -i -pe's/\Q$ENV{S}/$ENV{R}/g' file.txt
in my bash script i look for text inside a file and replace it with a variable from my bash script. I couldn't get the variable to be recognized by the perl command. any ideas?
mybash.bash:
#! /bin/sh
let "myNum=2"# myNum could be any integer
perl -pi -e 's/ABCD\d/ABCD$myNum/g' ./textfile.txt
textfile.txt:
'ABCD0' gets replace with 'ABCD' with above script
Use double quotes so as to enable interpolation of variables:
perl -pi -e "s/ABCD\d/ABCD$myNum/g" ./textfile.txt
^^^ ^^^
Have you tried using $($myNum) ? Bash needs to be able to execute/evaluate the variable?
Also, single quotes print literal fields usually and double evaluate things, so you might need to fiddle with that if the above doesn't work