Operating System - Linux
1825931 Members
3120 Online
109689 Solutions
New Discussion

Re: perl, shell problem with quotes, escaping

 
SOLVED
Go to solution
Paul Glass
Advisor

perl, shell problem with quotes, escaping

In a shell script to manage user accounts I want to modify this line in their .profile.

X_ENV=${X_VECT}00n02 #old line
X_ENV=${X_VECT}23n02 #new line

where 23 is a number found earlier in script.

This works fine on a test .profile :-
export NCODE="23" #set it here for testing
perl -pi.old -e '$NCODE=$ENV{NCODE}; \
-e s/^X_ENV=\$\{X_VECT\}00n02/X_ENV=\$\{X_VECT\}${NCODE}n02/' ./.profile

but to run it on a user's write-protected .profile I do:-

su root -c "perl -pi.old -e '$NCODE=$ENV{NCODE}; \
-e s/^X_ENV=\$\{X_VECT\}00n02/X_ENV=\$\{X_VECT\}${NCODE}n02/' ./profile"

and get errors:-
Backslash found where operator expected at -e line 1, near "X_VECT\"
Backslash found where operator expected at -e line 1, near "X_VECT\"
Can't modify constant item in scalar assignment at -e line 1, near "};"
syntax error at -e line 1, near "X_VECT\"
Execution of -e aborted due to compilation errors.

I've tried escaping and quoting differently, but still can't make it work. The rest of the script needs to be run as a regular user, not root, hence the need for "su root -c".

Any advice would be much appreciated.

Paul
8 REPLIES 8
H.Merijn Brand (procura
Honored Contributor

Re: perl, shell problem with quotes, escaping

By far the easiest solution would be to write the script to a local .pl or .sh file and execute that in su

# su root -c 'perl /tmp/_x23.pl'

or

# su root -c 'sh /tmp/_x23.sh'

Enjoy, Have FUN! H.Merijn
Enjoy, Have FUN! H.Merijn
Paul Glass
Advisor

Re: perl, shell problem with quotes, escaping

Thanks, but I was hoping to keep it tidy, all in the one script file.
Oviwan
Honored Contributor

Re: perl, shell problem with quotes, escaping

hey

perhaps you can find here some ideas with quotes: http://sial.org/howto/perl/one-liner/

Regards
A. Clay Stephenson
Acclaimed Contributor
Solution

Re: perl, shell problem with quotes, escaping

Quoting isn't so hard. The main rule that you have to remember is that nothing inside single quotes is instantiated whereas variables with double quotes are instantiated. The only other rule is that special character must be escaped with \.

Since you didn't like Merjin's approach, there is a way to have your cake and eat it too: build your Perl script "on the fly" within a shell script and then invoke it from the shell. You can even store a complete Perl script in a shell variable:
------------------------------------------
#!/usr/bin/sh

build_P1()
{
typeset V1=${1} # shell variables
typeset V2=${2}
shift 2

echo "my \$v1 = ${V1};"
echo "my \$v2 = ${V2};"
echo "print \"One\\n\";"
echo "print \"Two\\n\";"
echo "print \"v1 = \",\$v1,\"\\n\";"
echo "print \"v2 = \",\$v2,\"\\n\";"
return 0
} # build_P1

typeset X=$(build_P1 100 999)
typeset -i STAT=0

perl -e "${X}"
STAT=${?}
exit ${STAT}
-------------------------------------------

This example doesn't perform your task but it does illustrate the necessary techniques. Note that I passed 2 variables into the build_P1 function and these were assigned as Perl variables before being printed. I also printed 2 string constants. Note also that by storing the script in a shell variable, no temporary file is even needed. This is a fairly good technique for build complex awk, sed, Perl, or other shell scripts "on the fly".
If it ain't broke, I can fix that.
James R. Ferguson
Acclaimed Contributor

Re: perl, shell problem with quotes, escaping

Hi Paul:

I would agree with Merijn for the sake of simplicity.

Consider this, though. Instead of mixing Perl and a shell script, since you said that you were "hoping to keep it tidy, all in the one script file", re-write the shell script in Perl in its entirety :-)

Regards!

...JRF...


Peter Nikitka
Honored Contributor

Re: perl, shell problem with quotes, escaping

Hi,

the command does exactly what you tell him (as usual): the outer most double quotes -
su root -c ".."
tell the shell to look for substitutions. It doesn't matter that you have single quotes inside this string: they are just literal single quotes.
Simply exchanging single and double quotes would perform the expansion in the shell invocation by the su command. So you have to split the commandline into pieces, so by the last puzzling of su still no expansion is performed. Such you do not have to quote every single $,... but only inject a single quote in the beginning and at the end of the "second level command" via "'". Look at the trace output of
set -x
su root -c 'set -x;print -u2 '"'"'a\t$PATH\n$RANDOM'"'"

You'll see
+ su root -c set -x;print -u2 'a\t$PATH\n$RANDOM'
Password:
+ print -u2 a\t$PATH\n$RANDOM
a $PATH
$RANDOM

Nevertheless: I would prefer Merjin's suggestion.

mfG Peter
The Universe is a pretty big place, it's bigger than anything anyone has ever dreamed of before. So if it's just us, seems like an awful waste of space, right? Jodie Foster in "Contact"
Paul Glass
Advisor

Re: perl, shell problem with quotes, escaping

Thanks all of you for your advice.

After considering what the extra shell for su was doing I made it work by some extra escapes :-

su root -c "perl -pi.old -e '\$NCODE=\$ENV{NCODE};' \
-e 's/^X_ENV=\\$\{X_VECT\}00n02/X_ENV=\\$\{X_VECT\}${NCODE}n02/' ./.profile"

but this is not easy to read so I have rewritten it the way that A Clay Stephenson suggested. This will make it easier to maintain in the future.
Paul Glass
Advisor

Re: perl, shell problem with quotes, escaping

Fixed