Get expect to take a variable with whitespaces in it [duplicate] - linux

This question already has an answer here:
When should I double-quote a parameter expansion? [duplicate]
(1 answer)
Closed 3 years ago.
In my expect script I have two variables I would like to add. Both of them will be variables into the script.
hello="My Life"
world="is wonderful"
./script.sh $hello $world
in script.sh
#!/usr/bin/expect
set timeout 10
match_max 100000000
set first_var [lindex $argv 0]
set second_var [lindex $argv 1]
Currently,
first_var="My"
second_var="Life"
The code below works as expected when don't pass in them in as variables.
./script.sh 'My Life' 'is wonderful'
I need to know how to have that script take in the variables and still ignore white space within them.

You must pass the variables within quotes as well;
./script.sh "$hello" "$world"
The way Bash expansion works, these variables will be expanded out before the script is run. It will be the same as if the command were run as
./script "My life" "is wonderful"
The quotes around parameters indicate to the shell not to split via the field separator.

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

Why the assignment of an array string (with brackets) to environment variable is not working [duplicate]

This question already has answers here:
I just assigned a variable, but echo $variable shows something else
(7 answers)
Closed 2 years ago.
Execute the following command in bash shell:
export sz1='"authorities" : ["uaa.resource"]'
Now, try echo $sz1
I expect to see the following output:
"authorities" : ["uaa.resource"]
But instead I get this:
"authorities" : c
The interesting thing is that I have dozens of servers where I can execute this type of variable assignment and it works except on this server. This server has exactly the same OS version, profile, bash version etc. What could be the reason for this behavior?
Always quote your variables. Use
echo "$sz1"
When you don't quote the variable, word splitting and wildcard expansion is done on the variable expansion. On ["uaa.resource"] is a wildcard that will match any of the following filenames:
"
u
a
.
r
e
s
o
u
c
On that one machine you have a file named c, so the wildcard matches and gets replaced with that filename.

Bash execute string as command without expanding escaped spaces [duplicate]

This question already has answers here:
Why does shell ignore quoting characters in arguments passed to it through variables? [duplicate]
(3 answers)
How can I store a command in a variable in a shell script?
(12 answers)
Closed 2 years ago.
I have an external executable that I need to pass arguments to. With a bash script, I have code that determines these arguments. Some arguments may have escaped spaces.
I need to then execute that string, without expanding each of the arguments.
# ... some code that determines argument string
# the following is an example of the string
ARGSTR='./executable test\ file.txt arg2=true'
exec ${ARGSTR}
I must have the $ARGSTR be expanded so that I can pass arguments to ./executable, but each of the arguments should not be expanded. I have tried quoting "test file.txt", but this still does not pass it as one argument to ./executable.
Is there a way to do something like this?
Us an array instead of a string:
#!/usr/bin/env bash
ARGSTR=('./executable' 'test file.txt' 'arg2=true')
exec "${ARGSTR[#]}"
See:
BashFAQ-50 - I'm trying to put a command in a variable, but the complex cases always fail.
https://stackoverflow.com/a/44055875/7939871
This may achieve what you wanted :
ARGSTR='./executable test\ file.txt arg2=true'
exec bash -c "exec ${ARGSTR}"

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.

output from expect is not complete

I have this script in order to make rsync with another server, the propossal is to get arround 1600 files, this script as two variables, date and hour, so, I send these two values with shell script then I pass the values.
Expect script:
#!/usr/bin/expect
set DIR_DATE [lrange $argv 0 0]
# Define date variable.
set DT_HOUR [lrange $argv 1 1]
# Define hour variable.
spawn rsync -avzb -e ssh user#IPSERVER:/SOURCE_DIR/$DIR_DATE/A$DIR_DATE.$DT_HOUR*.txt /TARGET_DIR/$DIR_DATE/
expect "password:"
send "PASSWORD\r"
#interact
expect eof
And the shell script is:
#!/bin/bash
***HERE is the code to get date and hour variable: DT_DATE,DT_HOUR; then, next step is run the expect script***
${DIR_BIN}/rsync_expect.sh ${DT_DATE} ${DT_HOUR}
You can note, in the expect script, I comment "interactive" word, because:
If it is not comment and run manually the script, it runs very well, it get 1600 files.
If it is commented, and run through the shell script, it only get arround 50 files and that's off.
So, any sugestion in order to get all files using shell scripts?
You're probably timing out: 50 files is probably what you can transfer in (default) 10 seconds. Add this before you spawn: set timeout -1
".sh" is a bad file extension for an expect script: use ".exp"
The lrange command returns a list. Use lassign $argv DIR_DATE DT_HOUR

Resources