How can I write Shell script for default parameter setting - linux

In shell script, How can I set 0 as default value to parameter.
param2=0
${2:-0}
and
${2:-param2}
These result is 0: not found
and
param=$5
S{1:-$param}
is active. but $0 mean shell script name. I want to use number 0.

echo "param: $param" # param is not defined
echo "param: ${param-0}" # use 0 as default
param=99 # set a value for param
echo "param: ${param-0}" # ignore the default
output:
param:
param: 0
param: 99

To understand problems like this, add set -x before the code. That will tell you that ${2:-0} is expanded to 0. The shell thinks this is a command and tries to execute it.
This will be easier to understand if you look at this code:
cmd=echo
${cmd} test
If you run this, ${cmd} is replaced with echo.
In your code, you probably want to assign the result of ${2:-0} to a new variable:
foo=${2:-0}

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

Modify global variable from loop

Why do I get
/tmp/test: line 4: 0=Done: command not found
from the below
a="0"
while [ true ]; do
$a="Done"
exit
done
echo $a
I were expecting it would output Done.
You don't need to use the $ when defining a variable, only when you are accessing it.
You'll need to change the line defining the variable a to:
a="Done"
As to an explanation, what I believe is happening here is that $a is being resolved to 0 and then the shell is seeing the entire 0=Done as a single (unfound) command. Accessing undefined variables still returns a 0 exit code.

Strange behavior of shell output file ( Linux )

Do you know why below shell script just generates the output file named 'Loading_EMP.sql' instead of 'Loading_1_EMP.sql'?
#!/bin/bash
JOBID="1"
TABLE="EMP"
echo 'test' > Loading_$JOBID_$TABLE.sql;
# Output
Loading_EMP.sql
# Expected Output
Loading_1_EMP.sql
echo 'test' > Loading_${JOBID}_${TABLE}.sql;
should do it, or better
echo 'test' > "Loading_${JOBID}_${TABLE}.sql" # to avoid word splitting
In Loading_$JOBID_$TABLE, shell trates $JOBID_ as a single variable and since it is not set, it substitutes $JOBID_ with nothing resulting in Loading_EMP.sql
This [ answer ] must read for you.
_ is not a special character in shell. So the shell sees this as you echoing a $JOBID_ variable, which is undefined, and thus empty. Instead, you should explicitly show the shell what your variables are by using {}:
echo 'test' > Loading_${JOBID}_${TABLE}.sql;
# Here -----------------^-----^--^-----^
The interpreter thinks you are referring to a variable named JOBID_. Enclose the name with {}.
echo 'test' > Loading_${JOBID}_$TABLE.sql

Bash config file or command line parameters

If I am writing a bash script, and I choose to use a config file for parameters. Can I still pass in parameters for it via the command line? I guess I'm asking can I do both on the same command?
The watered down code:
#!/bin/bash
source builder.conf
function xmitBuildFile {
for IP in "{SERVER_LIST[#]}"
do
echo $1#$IP
done
}
xmitBuildFile
builder.conf:
SERVER_LIST=( 192.168.2.119 10.20.205.67 )
$bash> ./builder.sh myname
My expected output should be myname#192.168.2.119 and myname#10.20.205.67, but when I do an $ echo $#, I am getting 0, even when I passed in 'myname' on the command line.
Assuming the "config file" is just a piece of shell sourced into the main script (usually containing definitions of some variables), like this:
. /etc/script.conf
of course you can use the positional parameters anywhere (before or after ". /etc/..."):
echo "$#"
test -n "$1" && ...
you can even define them in the script or in the very same config file:
test $# = 0 && set -- a b c
Yes, you can. Furthemore, it depends on your architecture of script. You can overwrite parametrs with values from config and vice versa.
By the way shflags may be pretty useful in writing such script.

Accessing variable from ARGV

I'm writing a cPanel postwwwact script, if you're not familiar with the script its run after a new account is created. it relies on the user account variable being passed to the script which i then use for various things (creating databases etc). However, I can't seem to find the right way to access the variable i want. I'm not that good with shell scripts so i'd appreciate some advice. I had read somewhere that the value i wanted would be included in $ARGV{'user'} but this simply gives "root" as opposed to the value i need. I've tried looping through all the arguments (list of arguments here) like this:
#!/bin/sh
for var
do
touch /root/testvars/$var
done
and the value i want is in there, i'm just not sure how to accurately target it. There's info here on doing this with PHP or Perl but i have to do this as a shell script.
EDIT Ideally i would like to be able to call the variable by something other than $1 or $2 etc as this would create issues if an argument is added or removed
..for example in the PHP code here:
function argv2array ($argv) {
$opts = array();
$argv0 = array_shift($argv);
while(count($argv)) {
$key = array_shift($argv);
$value = array_shift($argv);
$opts[$key] = $value;
}
return $opts;
}
// allows you to do the following:
$opts = argv2array($argv);
echo $opts[‘user’];
Any ideas?
The parameters are passed to your script as a hash:
/scripts/$hookname user $user password $password
You can use associative arrays in Bash 4, or in earlier versions of Bash you can use built up variable names.
#!/bin/bash
# Bash >= 4
declare -A argv
for ((i=1;i<=${##};i+=2))
do
argv[${#:i:1}]="${#:$((i+1)):1}"
done
echo ${argv['user']}
Or
#!/bin/bash
# Bash < 4
for ((i=1;i<=${##};i+=2))
do
declare ARGV${#:i:1}="${#:$((i+1)):1}"
done
echo ${!ARGV*} # outputs all variable names that begin with ARGV
echo $ARGVuser
Running either:
$ ./argvtest user dennis password secret
dennis
Note: you can also use shift to step through the arguments, but it's destructive and the methods above leave $# ($1, $2, etc.) in place.
#!/bin/bash
# Bash < 4
# using shift (can use in Bash 4, also)
for ((i=1;i<=${##}+2;i++))
do
declare ARGV$1="$2"
# Bash 4: argv[$1}]="$2"
shift 2
done
echo ${!ARGV*}
echo $ARGVuser
If it's passed as a command-line parameter to the script, it's available as $1 if it's first parameter, $2 for the second, and so on.
Why not start off your script with something like
ARG_USER=$1
ARG_FOO=$2
ARG_BAR=$3
And then later in your script refer to $ARG_USER, $ARG_FOO and $ARG_BAR instead of $1, $2, and $3. That way, if you decide to change the order of arguments, or insert a new argument somewhere other than at the end, there is only one place in your code that you need to update the association between argument order and argument meaning.
You could even do more complex processing of $* to set your $ARG_WHATEVER variables, if it's not always going to be that all of the are specified in the same order every time.
You can do the following:
#!/bin/bash
for var in $argv; do
<do whatver you want with $var>
done
And then, invoke the script as:
$ /path/to/script param1 arg2 item3 item4 etc

Resources