Declaring User Defined Variable in Shell Scripting (csh shell) - linux

I am trying to learn shell scripting and trying to create a user defined variable within the script, first:
howdy="Hello $USER !"
echo $howdy
However, when I execute the script (./first) I get this:
howdy=Hello aaron!: Command not found.
howdy: Undefined variable.
What am I doing wrong?

You have two errors in you code:
you are using sh syntax instead of csh one to set the variable
you are not escaping the "!" character (history substitution)
Try this:
#!/bin/csh
set howdy="Hello $USER \!"
echo $howdy

csh expects that you set variables. Try
set howdy="Hello $USER"
echo $howdy

You are doing
howdy=''Hello $USER !''
You need to enclose the string in double quotes as:
howdy="Hello $USER !"
You seem to be using two single quotes in place of a double quote.

Related

Pass in bash terminal variables to a bash script

If I am in a Linux terminal and I start setting variables such as export AGE=45.
Then I have a script to read user data from terminal variables and process it, is this possible to do?
IE:
user#linux$ export AGE=45
user#linux$ ./age.sh
#script asks for input
read -p "what is your age?" scriptAGE
#user inputs variable set in terminal
$AGE
#echo output
echo "your age is: " $scriptAGE"
#should say your age is: 45
There is no such thing as a terminal variable. read just assigns a string to your variable scriptAGE.
If this string contains some $NAME you want to expand, you could apply eval to it, but this is of course extremely dangerous because of possible code injection.
A safer way to do this is using envsubst, but this requires that the variables to be substituted must be environment variables. In your case, AGE is in the environment, so this condition is met.
In your case, you would have to do therefore a
envsubst <<<"$scriptAGE"
which would print on stdout the content of scriptAGE with all environment variables in it substituted.
Variables are not expanded in input, only in the script itself.
You could use eval to force it to process the variable value as shell syntax.
eval "echo 'your age is:' $scriptAGE"
But this will also process other shell syntax. If they enter $AGE; rm * it will say their age is 45 and then delete all their files.
you could just do
age=$1
echo "Your age is $1"
where $1, $2, $3, .., $N are the passed arguments by order
And then run your script
bash script sh Noureldin
For more Info read this:
passing names args

Passing multiple variables from local bash to remote bash script without gobbling

I'm having trouble sending multiple variables to a remote bash script without gobbling occurring.
For the sake of this question the variable $timestamp contains 12-12-15 19:45:21
ssh user#serverip "/usr/path/to/script.sh http://www.web.com/$1 http://web.com/$2 $timestamp";
I am sending 3 variables to script.sh
Two URLs with an amended file name in the form of a variable on the end and then my $timestamp variable
But on myscript.sh, when I try to insert $timestamp into a mysql database it only see's the first part of the date before the white space :
12-12-15
So my quotes around the command aren't preventing gobbling. Do I need to quote each variable separately?
ssh user#serverip "/usr/path/to/script.sh http://www.web.com/$1 http://web.com/$2 $timestamp";
This is equivalent to this locally calling
/usr/path/to/script.sh http://www.web.com/$1 http://web.com/$2 $timestamp
Try to quote each individual argument passed
ssh user#serverip "/usr/path/to/script.sh 'http://www.web.com/$1' 'http://web.com/$2' '$timestamp'";
You can also print each argument in the script to see what's being passed... e.g. echo $1, etc.
You can try something like
ssh localhost "printf \"%s %s %s\n\" a b \"last parameter\""
You need to escape the values for the remote host. The correct way of doing this is with printf %q:
ssh user#serverip "/usr/path/to/script.sh \
$(printf "%q " "http://www.web.com/$1" "http://web.com/$2" "$timestamp")"
This works for all variable values. Wrapping them in single quotes would instead result in syntax error and command injection when the variables themselves contain single quotes.

LD_PRELOAD - shell expansion trouble

I want to call an executable with LD_PRELOAD-ing some .so files.
But I have a problem, that bash shell expansion seems not to work in variable expansion:
These are the files, I'm trying to set for LD_PRELOAD:
nuclear#Korhal:~$ ls speedhack/speedhack*.so
speedhack/speedhack32.so speedhack/speedhack.so
But the shell expansion does not work here:
nuclear#Korhal:~$ LD_PRELOAD="speedhack/speedhack*.so" ./my_executable
ERROR: ld.so: object 'speedhack/speedhack*.so' from LD_PRELOAD cannot be preloaded: ignored.
I wrote a script to check, what happens with shell variables expansion:
nuclear#Korhal:~$ cat test.sh
#!/bin/bash
echo "LD_PRELOAD w/o quotes:"
echo $LD_PRELOAD
echo "LD_PRELOAD with quotes:"
echo "$LD_PRELOAD"
Running it:
nuclear#Korhal:~$ LD_PRELOAD="speedhack/speedhack*.so" ./test.sh
ERROR: ld.so: object 'speedhack/speedhack*.so' from LD_PRELOAD cannot be preloaded: ignored.
LD_PRELOAD w/o quotes:
speedhack/speedhack32.so speedhack/speedhack.so
LD_PRELOAD with quotes:
speedhack/speedhack*.so
But it gets more complicated: the star is not expanded when variable is accessed from ld.so
and inside the script it gets expanded only if I have no quotes in echo.. As I know, double quotes make no difference in variable expansion (echo $VAR should be the same as echo "$VAR". But echo '$VAR' will print the string $VAR)
The main question: How to force shell expansion in variable assignment, so that LD_PRELOAD holds the list of files?
You can put the filenames in an array and use that to expand the list:
FILES=(speedhack/speedhack*.so)
LD_PRELOAD="${FILES[#]}" ./my_executable
You can also use backquotes or $() syntax to copy-paste the results of a command onto a command-line. Then use double quotes to grab all the words into the same variable.
LD_PRELOAD="$(ls speedhack/speedhack*.so)" ./my_executable

Shell script for setting environment variable

I am writing a shell script to set the environment variables whose values are available in a file. Below is the shell script I wrote,
VARIABLE_FILE=env-var.dat
if [ -f ${VARIABLE_FILE} ] ; then
. ${VARIABLE_FILE}
if [ ! -z "${TEST_VAR1}" ] ; then
export TEST_VAR1="${TEST_VAR1}"
fi
if [ ! -z "${TEST_VAR2}" ] ; then
export TEST_VAR2="${TEST_VAR2}"
fi
fi
The above code works only in bash shell, since I have used export command to set the environment variable and it fails if I used it with any other shell. Is there is any command to set the environment variable which works in any shell ?
"Fancier" shells like bash and zsh permit you to set a variable and export it as an environment variable at the same time like so:
export FOO=bar
With a standard POSIX bourne shell, the equivalent is achieved by doing it in two commands:
FOO=bar
export FOO
Note that once you've exported a variable, you can reset it to a different value later in the script and it's still exported (you don't need to export it again). Also, you can export several variables at a time:
FOO=bar
BAZ=quux
export FOO BAZ
You mentioned tcsh in your comment, but csh and derivatives are completely different from bourne-based shells (and not recommended for use!). You can rarely make a shell script compatible with both sh and csh at the same time. For csh, look into setenv
If you really want this to happen, it can be done, but it's tricky. One way to do it is to use awk to output the correct syntax and evaluate the text coming back from awk. To share a single environment variable value file between major sh and csh flavors, the following command in a file will import a variable value file to the environment: (yes, yes, it's one huge line, due to the inflexible way that some shells treat the backticks. If you didn't mind having a .awk file too, you could use awk -f...)
eval `awk '{ var = $1; $1=""; val=substr($0,2); if ( ENVIRON["SHELL"] ~ /csh$/) { print "setenv", var, " \"" val "\";" } else { print var "=\"" val "\"" ; print "export", var }}' $HOME/env_value_file`
The variable value file is in this format:
FOO value for foo
BAR foo bar
BAZ $BAR plus values $FOO
Design notes for educational purposes:
In awk, there's no easy way of accessing fields 2-NF, so if there
could be spaces in our variable values we need to modify $1 to get
$0 to be close to get the value we want.
To get this to work, since a SHELL variable is always set, but not as an
environment variable and not with a consistent capitalization, you have to wet
a SHELL environment variable from the shell's value as below.
as an environment variable before you use the script.
Also, if you want the new environment values to be present after the import
environment script you need to source the environment script.
If a shell doesn't do eval well, you'll have to tweak the script.
For bourne shell flavors (bash, sh, ksh, zsh):
export SHELL
. import_environment
For csh flavors: (shell variable tends to be lower case in csh shells)
setenv SHELL "$shell"
source import_environment

Bash Shell - The : Command

The colon command is a null command.
The : construct is also useful in the conditional setting of variables. For example,
: ${var:=value}
Without the :, the shell would try to evaluate $var as a command. <=???
I don't quite understand the last sentence in above statement. Can anyone give me some details?
Thank you
Try
var=badcommand
$var
you will get
bash: badcommand: command not found
Try
var=
${var:=badcommand}
and you will get the same.
The shell (e.g. bash) always tries to run the first word on each command line as a command, even after doing variable expansion.
The only exception to this is
var=value
which the shell treats specially.
The trick in the example you provide is that ${var:=value} works anywhere on a command line, e.g.
# set newvar to somevalue if it isn't already set
echo ${newvar:=somevalue}
# show that newvar has been set by the above command
echo $newvar
But we don't really even want to echo the value, so we want something better than
echo ${newvar:=somevalue}.
The : command lets us do the assignment without any other action.
I suppose what the man page writers meant was
: ${var:=value}
Can be used as a short cut instead of say
if [ -z "$var" ]; then
var=value
fi
${var} on its own executes the command stored in $var. Adding substitution parameters does not change this, so you use : to neutralize this.
Try this:
$ help :
:: :
Null command.
No effect; the command does nothing.
Exit Status:
Always succeeds.

Resources