what's the difference of echoing the variables in this way? - bash

What is the difference of echoing these variable in bash scripting?
EXAMPLE:
I declare a variable
VARIABLE="Hello World"
echo $VARIABLE
What's the difference between the one above and this below?
echo ${VARIABLE}
Does it make a difference if I put {} or not?

No difference in your code
The curly braces, To delimiting a variable name are used for parameter expansion so you can do things like
Truncate a variable' content
$ var="abcde"; echo ${var%e*}
abcd
Make substitutions similar to sed
$ var="abcde"; echo ${var/e/1}
abcd1
Braces can also be useful when the expansion occurs in certain contexts. For example:
FOO=bar
echo $FOO1 # tries to print the value of a variable named "FOO1"
echo ${FOO}1 # prints "bar1"

Related

Expand a variable within variable right before echo

Example:
testing="test"
var="\"${testing} the variable\""
testing="Update"
echo "$var"
Output:
test the variable
Required output:
Update the variable
Variables are expanded when the string is used, they're not templates that remember the variable substitution.
If you need to do this, you need to put the variable literally into the string, and use eval.
testing="test"
var='"${testing} the variable"'
testing="Update"
eval "echo $var"
But eval is dangerous -- it will execute any shell commands in the string. A better solution would probably be to use some kind of placeholder string and replace it using the shell expansion operator.
var='#testing# the variable'
testing="Update"
echo "${var//#testing#/$testing}"

Could someone explain me what this shell bash command "echo{,}" means?

If I do this:
echo{,}
The result is:
echo
I don't really understand the {,} at the end and the result
Thanks to clarify this.
I would start with something simpler to see how {} works: As #anubhava linked, it generates strings. Essentially, it expands all the elements in it and combines them with whatever is before and after it (space is separator if you don't quote).
Example:
$ bash -xc 'echo before{1,2}after and_sth_else'
+ echo before1after before2after and_sth_else
before1after before2after and_sth_else
Note that there is a space between echo and the arguments. This is not the case on what you have posted. So what happened there? Check the following:
$ bash -xc 'man{1,2}'
+ man1 man2
bash: man1: command not found
The result of the expansion is fed to bash and bash tries to execute it. In the above case, the command that is looking for is man1 (which does not exist).
Finally, combine the above to your question:
echo{,}
{,} expands to two empty elements/strings
These are then prefixed/concatenated with "echo" so we now have echo echo
Expansion finished and this is given to bash to execute
Command is echo and its first argument is "echo"... so it echoes echo!
echo{,}
is printing just echo because it is equivalent of echo echo.
More examples to clarify:
bash -xc 'echo{,}'
+ echo echo
echo
echo foo{,}
foo foo
echo foo{,,}
foo foo foo
More about Brace Expansion
Brace expansion is a mechanism by which arbitrary strings may be generated. This mechanism is similar to pathname expansion, but the filenames generated
need not exist. Patterns to be brace expanded take the form of an optional preamble, followed by either a series of comma-separated strings or a sequence
expression between a pair of braces, followed by an optional postscript. The preamble is prefixed to each string contained within the braces, and the
postscript is then appended to each resulting string, expanding left to right.
The {item1,item2,...} is a brace expansion.
So echo{,} is expanded as echo echo because {,} has two (empty) elements, then echo prints it argument.
Try this :
$ set -x
$ echo{,}
+ echo echo
echo
$ set +x
+ set +x
$
It's also handy to generate "cross products" without nested loops:
$ ary=( {1,2,3}{a,b,c} )
$ declare -p ary
declare -a ary=([0]="1a" [1]="1b" [2]="1c" [3]="2a" [4]="2b" [5]="2c" [6]="3a" [7]="3b" [8]="3c")

How to print variable's value as literal string

Not sure if the title is precise. Let's say I have a variable with a string:
var=C:\Windows\file.exe
And I'd like to print it's value as if it were a literal string, i.e. I want to see this on the screen:
C:\Windows\file.exe
But, of course, the usual ways to print a variable don't do that:
echo $var
C:Windowsfile.exe
echo "$var"
C:Windowsfile.exe
echo '$var'
$var
Is it possible to do that?
The problem is that the backslashes are being operated on by shell at definition time, not when you are evaluating the variable later. You need to quote the declaration i.e. use any shell escaping mechanism to escape the \s.
Here is what you are doing:
$ var=C:\Windows\file.exe
$ echo "$var"
C:Windowsfile.exe
Here is what you need:
$ var='C:\Windows\file.exe'
$ echo "$var"
C:\Windows\file.exe

Script, save all $input into 1 variable

Example:
bash script.sh "hello world"
(in script echo "$1")
hello world
Question:
bash script.sh "good" "morning" "everybody"
What do I have to write in my script to output directly:
goodmorningeverybody
So, in general, I want $1, $2, $3, ... (can be 100 but I don't know) to be saved in one variable for example VAR1.
You can refer to all the positional arguments with $* and $#.
From 3.4.2 Special Parameters
*
Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, it expands to a single word with the value of each parameter separated by the first character of the IFS special variable. That is, "$*" is equivalent to "$1c$2c…", where c is the first character of the value of the IFS variable. If IFS is unset, the parameters are separated by spaces. If IFS is null, the parameters are joined without intervening separators.
#
Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, each parameter expands to a separate word. That is, "$#" is equivalent to "$1" "$2" …. If the double-quoted expansion occurs within a word, the expansion of the first parameter is joined with the beginning part of the original word, and the expansion of the last parameter is joined with the last part of the original word. When there are no positional parameters, "$#" and $# expand to nothing (i.e., they are removed).
So to get good morning everybody as output you could just use echo "$*" or echo "$#".
In general # is the more useful of the two variables.
However, if you really want the worlds all smushed together the way you indicate then you have a few options.
The most straightforward of which is a simple loop:
for word; do
s+=$word
done
(for without the in <list> part operates on the positional arguments).
However, you can also do this with * by controlling IFS.
So you could also do s=$(IFS=; echo "$*"). You want/need the sub-shell to avoid setting IFS for the current shell.
Try doing this:
#!/bin/sh
var=$(printf '%s' "$#")
echo "$var"
or even better, credits to chepner :
printf -v var '%s' "$#"
or
#!/bin/bash
for arg; do
str+="$arg"
done
echo "$str"
Output :
goodmorningeverybody
Note :
"$#" expands to each positional parameter as its own argument: "$1" "$2" "$3"...
You could do it with a loop:
for x in "$#"; do
input="$input$x"
done
You can do it using Shell-Parameter-Expansion in this way:
#!/bin/bash
VAR="$*"
VAR=${VAR// /}
echo $VAR
Example
$ script.sh "good" "morning" "everybody"
goodmorningeverybody

How to use a variable's value as another variable's name in bash [duplicate]

This question already has answers here:
Dynamic variable names in Bash
(19 answers)
Closed 6 years ago.
I want to declare a variable, the name of which comes from the value of another variable, and I wrote the following piece of code:
a="bbb"
$a="ccc"
but it didn't work. What's the right way to get this job done?
eval is used for this, but if you do it naively, there are going to be nasty escaping issues. This sort of thing is generally safe:
name_of_variable=abc
eval $name_of_variable="simpleword" # abc set to simpleword
This breaks:
eval $name_of_variable="word splitting occurs"
The fix:
eval $name_of_variable="\"word splitting occurs\"" # not anymore
The ultimate fix: put the text you want to assign into a variable. Let's call it safevariable. Then you can do this:
eval $name_of_variable=\$safevariable # note escaped dollar sign
Escaping the dollar sign solves all escape issues. The dollar sign survives verbatim into the eval function, which will effectively perform this:
eval 'abc=$safevariable' # dollar sign now comes to life inside eval!
And of course this assignment is immune to everything. safevariable can contain *, spaces, $, etc. (The caveat being that we're assuming name_of_variable contains nothing but a valid variable name, and one we are free to use: not something special.)
You can use declare and !, like this:
John="nice guy"
programmer=John
echo ${!programmer} # echos nice guy
Second example:
programmer=Ines
declare $programmer="nice gal"
echo $Ines # echos nice gal
This might work for you:
foo=bar
declare $foo=baz
echo $bar
baz
or this:
foo=bar
read $foo <<<"baz"
echo $bar
baz
You could make use of eval for this.
Example:
$ a="bbb"
$ eval $a="ccc"
$ echo $bbb
ccc
Hope this helps!
If you want to get the value of the variable instead of setting it you can do this
var_name1="var_name2"
var_name2=value_you_want
eval temp_var=\$$var_name1
echo "$temp_var"
You can read about it here indirect references.
You can assign a value to a variable using simple assignment using a value from another variable like so:
#!/usr/bin/bash
#variable one
a="one"
echo "Variable a is $a"
#variable two with a's variable
b="$a"
echo "Variable b is $b"
#change a
a="two"
echo "Variable a is $a"
echo "Variable b is $b"
The output of that is this:
Variable a is one
Variable b is one
Variable a is two
Variable b is one
So just be sure to assign it like this b="$a" and you should be good.

Resources