Variable indirection


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Variable indirection
# 1  
Old 05-16-2012
Variable indirection

Hello.

This an issue from previous thread :https://www.unix.com/shell-programmin...ds-stdout.html

In a script, I want to print what command is to be being executed.
Generally I use :
Code:
CMD="some simple command"
echo "COMMAND : $CMD"
$CMD


Now
echo "COMMAND : $CMD" show this :
Code:
COMMAND : CNT=$(  grep -c -e  "Non-option program arguments: 'nxclient'" -e   "Checking whether to refresh metadata for zypper_local"  -e  "Selecting 'nxclient-3.5.0-7.x86_64' from repository 'zypper_local' for installation."  /tmp/nxclient_install_log.txt )

Which is correct; and should give CNT=3 which is correct.
But when I try to execute $CMD I get this error :

Code:
/root/bin/freenx_install_server_function: line 102: CNT=$(: command not found

I have try
Code:
CMD="some simple command"
echo "COMMAND : $CMD"
${$CMD}

Which give also an error


How to execute $CMD with success.

Last edited by Scrutinizer; 05-27-2012 at 02:04 AM.. Reason: code tags
# 2  
Old 05-16-2012
Hi.

Here are a few methods:
Code:
#!/usr/bin/env bash

# @(#) s1	Demonstrate execution of created shell command.

pe() { for _i;do printf "%s" "$_i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }
db() { ( printf " db, ";for _i;do printf "%s" "$_i";done;printf "\n" ) >&2 ; }
db() { : ; }
C=$HOME/bin/context && [ -f $C ] && $C

pl " Create, display, attempt to execute shell command:"
cmd='count=$( wc -l < s1 )'
pe " Command is \"$cmd\""
$cmd

pl " Write command to file, use as input to shell:"
echo "$cmd" > f1
echo "echo \$count" >> f1
cat f1
bash f1
pe " Current value of count is \"$count\""

pl " Write command to file with here document, use as input to shell:"
cat <<EOF > f1
$cmd
echo "count is \$count"
EOF
cat f1
bash f1
pe " Current value of count is \"$count\""

pl " Create, display, attempt to execute shell command, using eval:"
unset count
echo " count before eval is \"$count\""
cmd='count=$( wc -l < s1 )'
pe " Command is \"$cmd\""
pe " Current value of count is \"$count\""
eval $cmd
echo " count after  eval is \"$count\""

pl " Create, display, attempt to execute shell command, using source:"
unset count
echo " count before source is \"$count\""
cmd='count=$( wc -l < s1 )'
pe " Command is \"$cmd\""
echo "$cmd" > f1
pe " Current value of count is \"$count\""
source f1
echo " count after  source is \"$count\""

exit 0

producing:
Code:
% ./s1

Environment: LC_ALL = C, LANG = C
(Versions displayed with local utility "version")
OS, ker|rel, machine: Linux, 2.6.26-2-amd64, x86_64
Distribution        : Debian GNU/Linux 5.0.8 (lenny) 
bash GNU bash 3.2.39

-----
 Create, display, attempt to execute shell command:
 Command is "count=$( wc -l < s1 )"
./s1: line 14: count=$(: command not found

-----
 Write command to file, use as input to shell:
count=$( wc -l < s1 )
echo $count
51
 Current value of count is ""

-----
 Write command to file with here document, use as input to shell:
count=$( wc -l < s1 )
echo "count is $count"
count is 51
 Current value of count is ""

-----
 Create, display, attempt to execute shell command, using eval:
 count before eval is ""
 Command is "count=$( wc -l < s1 )"
 Current value of count is ""
 count after  eval is "51"

-----
 Create, display, attempt to execute shell command, using source:
 count before source is ""
 Command is "count=$( wc -l < s1 )"
 Current value of count is ""
 count after  source is "51"

See man bash for details.

Best wishes ... cheers, drl
# 3  
Old 05-16-2012
The double quotes around "some simple command" are causing the command substitution contained therein to be executed. Use single quotes to get the actual literal command displayed. Then, use eval to force the shell to evaluate the line where you want to run the command twice. The first pass replaces "eval $CMD" with "CNT=$(who|grep -c username)" then it gets executed.

eval can be dangerous if a user can affect what is eval'd, but since you are controlling the command to be eval'd you should be ok here.

Code:
$ cat x
#!/bin/ksh

CMD='CNT=$(who|grep -c username)'

print "COMMAND: $CMD"

eval $CMD

print $CNT

exit 0
$ x
COMMAND: CNT=$(who|grep -c username)
1
$

I note that one of drl's examples includes this method already.

Last edited by gary_w; 05-16-2012 at 11:53 AM..
# 4  
Old 05-16-2012
You might want to read this thread for a more detailed explanation about eval.

I hope this helps.

bakunin
# 5  
Old 05-19-2012
Seems to be not possible to use the same variable to print to screen and to execute when mixing single quote and double quote :

Code:
PACKAGE_1="nxclient"
REPOS_1="zypper_local"
LOG_FILE_1="/tmp/nxclient_install_log.txt"
CMD='CNT=$(  grep -c -e  "Non-option program arguments: '"'$PACKAGE_1'"'"  -e  "Checking whether to refresh metadata for '$REPO_1'" -e  "Selecting  '"'$PACKAGE_1-3.5.0-7.x86_64'"' from repository  '"'$REPO_1'"' for installation."    $LOG_FILE_1 ) '

echo $CMD give :
Code:
CNT=$(  grep -c -e  "Non-option program arguments: 'nxclient'"  -e  "Checking whether to refresh metadata for zypper_local" -e  "Selecting  'nxclient-3.5.0-7.x86_64' from repository  'zypper_local' for installation."    $LOG_FILE_1 )

I must separate the initial variable into 2 temporaries variables :
Code:
CMD_1='CNT=$(  grep -c -e  "Non-option program arguments: '"'$PACKAGE_1'"'"  -e  "Checking whether to refresh metadata for '$REPO_1'" -e  "Selecting  '"'$PACKAGE_1-3.5.0-7.x86_64'"' from repository  '"'$REPO_1'"' for installation."'
CMD_2="  $LOG_FILE_1 ) "
CMD=$CMD_1$CMD_2

Now echo $CMD give :
Code:
CNT=$(  grep -c -e  "Non-option program arguments: 'nxclient'"  -e  "Checking whether to refresh metadata for zypper_local" -e  "Selecting  'nxclient-3.5.0-7.x86_64' from repository  'zypper_local' for installation."  /tmp/nxclient_install_log.txt )

But to execute the command using eval I must use another temporary variable CMD_3:
Code:
CMD_3='CNT=$(  grep -c -e  "Non-option program arguments: '"'"'$PACKAGE_1'"'"'"  -e  "Checking whether to refresh metadata for $LOCK_INSTAL$REPO_1" -e  "Selecting '"'"'$PACKAGE_1-3.5.0-7.x86_64'"'"' from repository '"'"'$REPO_1'"'"' for installation."  $LOG_FILE_1 ) '
eval $CMD_3

The full script i_s now :

Code:
PACKAGE_1="nxclient"
REPOS_1="zypper_local"
LOG_FILE_1="/tmp/nxclient_install_log.txt"
CMD_1='CNT=$(  grep -c -e  "Non-option program arguments:  '"'$PACKAGE_1'"'"  -e  "Checking whether to refresh metadata for  '$REPO_1'" -e  "Selecting  '"'$PACKAGE_1-3.5.0-7.x86_64'"' from  repository  '"'$REPO_1'"' for installation."'
CMD_2="  $LOG_FILE_1 ) "
CMD=$CMD_1$CMD_2
echo $CMD
CMD_3='CNT=$(  grep -c -e  "Non-option program arguments:  '"'"'$PACKAGE_1'"'"'"  -e  "Checking whether to refresh metadata for  $LOCK_INSTAL$REPO_1" -e  "Selecting '"'"'$PACKAGE_1-3.5.0-7.x86_64'"'"'  from repository '"'"'$REPO_1'"'"' for installation."  $LOG_FILE_1 ) '
eval $CMD_3

The sample log file is here SUSE Paste

Any idea would be appreciated.
# 6  
Old 05-19-2012
It is indeed possible, but you have to be aware about the different number of times the line gets evaluated with and without eval.

If you use eval var='$(...)' to execute it you should probably print it with the same number of evals. But to be honest i have a feeling that your whole script is not planned very well because the structures you use are looking wrong anyway. I may be wrong, but if you post your whole script and tell us what you want to achieve we could find a better way to do it than with such crooked measures.

I hope this helps.

bakunin
# 7  
Old 05-20-2012
If you try double quotes instead of single quotes, I think it becomes a bit more straight forward, you should then escape the double quotes with a backslash, plus the $-signs that you wish to protect from evaluation during assignment:
Code:
CMD="CNT=\$( grep -c -e \"Non-option program arguments: '$PACKAGE_1'\" -e \"Checking whether to refresh metadata for $REPO_1\" -e \"Selecting '$PACKAGE_1-3.5.0-7.x86_64' from repository '$REPO_1' for installation.\" \"$LOG_FILE_1\" )"


If you use a here-document you do not need the double quotes around the string and therefore you do not need to escape the double quotes inside:
Code:
read CMD << EOF
CNT=\$( grep -c -e "Non-option program arguments: '$PACKAGE_1'" -e "Checking whether to refresh metadata for $REPO_1" -e "Selecting '$PACKAGE_1-3.5.0-7.x86_64' from repository '$REPO_1' for installation." "$LOG_FILE_1" )
EOF


And you need to use double quotes around variable references:
Code:
printf "%s\n" "$CMD"
eval "$CMD"


A third option, since this is just a deferred command in a variable and there is no reason for evaluating one $sign earlier than the next you could use:
Code:
read CMD << "EOF"
CNT=$( grep -c -e "Non-option program arguments: '$PACKAGE_1'" -e "Checking whether to refresh metadata for $REPO_1" -e "Selecting '$PACKAGE_1-3.5.0-7.x86_64' from repository '$REPO_1' for installation." "$LOG_FILE_1" )
EOF

Then you do not need to escape any character, but then the variable names will show up when you print the content of $CMD, which you may or may not prefer...
This User Gave Thanks to Scrutinizer For This Post:
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. UNIX for Advanced & Expert Users

Passing variable as input & storing output in other variable

I have a below syntax its working fine... var12=$(ps -ef | grep apache | awk '{print $2,$4}') Im getting expected output as below: printf "%b\n" "${VAR12}" dell 123 dell 456 dell 457 Now I wrote a while loop.. the output of VAR12 should be passed as input parameters to while loop and results... (5 Replies)
Discussion started by: sam@sam
5 Replies

2. Shell Programming and Scripting

[Solved] How to increment and add variable length numbers to a variable in a loop?

Hi All, I have a file which has hundred of records with fixed number of fields. In each record there is set of 8 characters which represent the duration of that activity. I want to sum up the duration present in all the records for a report. The problem is the duration changes per record so I... (5 Replies)
Discussion started by: danish0909
5 Replies

3. Red Hat

How to pass value of pwd as variable in SED to replace variable in a script file

Hi all, Hereby wish to have your advise for below: Main concept is I intend to get current directory of my script file. This script file will be copied to /etc/init.d. A string in this copy will be replaced with current directory value. Below is original script file: ... (6 Replies)
Discussion started by: cielle
6 Replies

4. Shell Programming and Scripting

Variable not found error for a variable which is returned from stored procedure

can anyone please help me with this: i have written a shell script and a stored procedure which has one OUT parameter. now i want to use that out parameter as an input to the unix script but i am getting an error as variable not found. below are the unix scripts and stored procedure... ... (4 Replies)
Discussion started by: swap21783
4 Replies

5. Shell Programming and Scripting

Not able to store command inside a shell variable, and run the variable

Hi, I am trying to do the following thing var='date' $var Above command substitutes date for and in turn runs the date command and i am getting the todays date value. I am trying to do the same thing as following, but facing some problems, unique_host_pro="sed -e ' /#/d'... (3 Replies)
Discussion started by: gvinayagam
3 Replies

6. Shell Programming and Scripting

Split variable length and variable format CSV file

Dear all, I have basic knowledge of Unix script and her I am trying to process variable length and variable format CSV file. The file length will depend on the numbers of Earnings/Deductions/Direct Deposits. And The format will depend on whether it is Earnings/Deductions or Direct Deposits... (2 Replies)
Discussion started by: chechun
2 Replies

7. Shell Programming and Scripting

How to define a variable with variable definition is stored in a variable?

Hi all, I have a variable say var1 (output from somewhere, which I can't change)which store something like this: echo $var1 name=fred age=25 address="123 abc" password=pass1234 how can I make the variable $name, $age, $address and $password contain the info? I mean do this in a... (1 Reply)
Discussion started by: freddy1228
1 Replies

8. Shell Programming and Scripting

Insert a line including Variable & Carriage Return / sed command as Variable

I want to instert Category:XXXXX into the 2. line something like this should work, but I have somewhere the wrong sytanx. something with the linebreak goes wrong: sed "2i\\${n}Category:$cat\n" Sample: Titel Blahh Blahh abllk sdhsd sjdhf Blahh Blah Blahh Blahh Should look like... (2 Replies)
Discussion started by: lowmaster
2 Replies

9. Shell Programming and Scripting

Sed variable substitution when variable constructed of a directory path

Hello, i have another sed question.. I'm trying to do variable substition with sed and i'm running into a problem. my var1 is a string constructed like this: filename1 filerev1 filepath1 my var2 is another string constructed like this: filename2 filerev2 filepath2 when i do... (2 Replies)
Discussion started by: alrinno
2 Replies

10. Shell Programming and Scripting

ksh: A part of variable A's name is inside of variable B, how to update A?

This is what I tried: vara=${varb}_count (( vara += 1 )) Thanks for help (4 Replies)
Discussion started by: pa3be
4 Replies
Login or Register to Ask a Question