In Bash, why `x=100 echo $x` doesn't print anything? [duplicate] - linux

This question already has answers here:
Why can't I specify an environment variable and echo it in the same command line?
(9 answers)
Closed 2 years ago.
I saw codes like this:
fqdn='computer1.daveeddy.com'
IFS=. read hostname domain tld <<< "$fqdn"
echo "$hostname is in $domain.$tld"
# => "computer1 is in daveeddy.com"
I think it works because IFS is assigned to . in the third line.. So I tried this:
x=100 echo $x
but found the bash doesn't print anything, while I expect it will print 100..
Moreover, I found x=100 echo $x; echo $x print nothing, while x=100; echo $x prints 100, which is very confusing.
Does anyone have ideas about this?

The $x is expanded before echo runs, and the result is passed to echo as an argument. echo does not use the value of x in its environment.
In the first example, read uses the value of IFS in its environment to split the string it receives via the here string.

here is another way to think about it:
$ a="echo 100" $a
This is equal to:
$ a="echo 100"
Because at the time of scanning the line, $a is empty. Variable substition occurs first, so the $a just disappears.
Compare this to a very similar statment:
$ a="echo 100"; $a # returns "100"

Related

How to assign variable to output of the program in bash? [duplicate]

This question already has answers here:
How to pass the value of a variable to the standard input of a command?
(9 answers)
Closed 11 months ago.
Here I have the simple code in which I am trying to store the value of program output to a variable in bash.
#!/bin/bash
i=0
for value in {1..10}
do
variable=`$value | ./unpackme`
str="What's my favorite number? Sorry, that's not it!"
if [[ "$variable" == "$str" ]]
then
echo "hello"
fi
done
The output I am getting is as follows:
Output screenshot
Please help me fix this. Thanks in advance.
You may try :
#!/bin/bash
str="What's my favorite number? Sorry, that's not it!"
for value in {1..10}; do
variable=$(./unpackme <<< "$value")
if [ "$variable" = "$str" ]; then
echo "hello"
fi
done
Some notes :
New style $(command) is preferred to `command`.
string in command <<< string is what is called a here string : command standard input is fed with string (think of it as : echo string | command).
[ "$variable" = "$str" ]: Take care of [[ "$a" == "$b" ]]/[[ "$a" = "$b" ]], they will consider the right part of ==/= as a pattern, and may not do what you want.

for loop not working when passed inside a string as an argument to eval [duplicate]

This question already has answers here:
Difference between single and double quotes in Bash
(7 answers)
Closed 1 year ago.
The following code when run as an individual command in shell script gives the expected result :
for x in This is good; do echo $x; done
[OUTPUT]
This
is
good
However when i pass it inside a string to Eval for some reason x is not being initialised
cmd = " for x in This is good; do echo $x ; done"
eval $cmd
[OUTPUT]
//Three blank lines
Why is x not being initialised ?
Use single quotes to assign to cmd so $x isn't already consumed at assignment time.
Also, put double quotes around your argument to eval (the bugs it prevents are more subtle, and don't impact your current string, but when you do hit them they're serious).
cmd='for x in This is good; do echo "$x"; done'
eval "$cmd"
Note echo "$x" instead of echo $x -- see I just assigned a variable, but echo $variable shows something different!

reload a variable string inside another string

I have to declare a string composed of different variables at the starting of a loop in order to print it later just with eval $command >> file.txt avoiding retype every time the string $command itself. But my $command string is composed of other variables and I need to be able to update them before printing. Here a brief example:
a=0
command="echo \"$a\""
for i in {1..2}; do
### change variable $a
a="$i"
### print command with the new $a
eval "$command"
done
### (it fails) result:
0
0
I need $a to be reloaded everytime in order to be substituted inside the $command string, thus the loop above will return
### wanted result
1
2
I know there are other strategies to achieve this, but I wonder if there is a specific way to reload a variable inside a string
Thank you very much in advance for any help!
You can use a function instead of a variable assignment
#!/usr/bin/env bash
a=0
command(){ echo "$1" ; }
for i in {1..2}; do
a="$i"
command "$a"
done
Edit: as per #glenn jackman one can use a global variable
command(){ echo "$a"; }
And just call the function without the argument $a
command
When you put a variable inside " its expanded. Use a single quote for command variable assignment.
$a=0
$command="echo \"$a\""
$echo $command
echo "0"
$command='echo \"$a\"'
$echo $command
echo \"$a\"
$
Try
a=0
command='echo $a'
for i in {1..2}; do
### change variable $a
a="$i"
### print command with the new $a
eval "$command"
done

When does a variable add $ in bash

I'm recently learning bash and confused when a variable would add $. I find code like:
i=1
while [ $i -le 10 ]
do
echo "$n * $i = `expr $i \* $n`"
i=`expr $i + 1`
done
The $ substitutes the variable. Writing $i will insert the value of i, no matter where you write it.
If you want to assign to the variable, that obviously makes no sense.
I thought #slaks' [ answer ] wouldn't be complete without this :
When not to add $ for a variable
With The Double-Parentheses [ Construct ]
x=5;
(( x++ )) # fine, note this construct accept $x form too.
When using export
var=stuff
export var #fine
When using declare
declare -a arry # fine
When not omit $
As #rici pointed out in the comment below:
you can leave out the $ in any arithmetic context, not just ((...))
and $((...)) ... For example, if arr is an array (not associative), then
${arr[x++]} is also fine.
Consider
# You wanted to create an associative array 'test' but you forgot to do
# declare -A test , Now below
test[foo]=bar # is foo a variable or a key, the reader isn't clear
# creates a simple array
echo ${test[foo]} # is foo a variable or a key?
bar
declare -p test
declare -a test='([0]="bar")'
# What happened?
# Since foo was not set at the point when 'test[foo]=bar' was called,
# bash substituted it with zero
# I meant to say test[foo]=bar hides an error.
A key thing to remember is that variables are never passed around in shell, only values. When you call something like
echo "$foo"
you might think that echo receives $foo, then looks at its value. Instead, the shell first expands $foo to the value of foo, then passes that value to echo.
The dollar sign is used to introduce any such parameter expansion, where the value of a parameter is needed. Consider:
$ foo=10
$ echo foo
foo
$ echo $foo
10
From the perspective of the echo command, there is no difference between echo $foo and echo 10; in both cases, the value passed to echo is 10.
To set a value to a variable in bash you can do
a=10
Where as to access the value of that variable you need to use
echo $a which mean $ is a symbol used to access the value of a variable.
i=1 ---> setting variable as 1
while [ $i -le 10 ] ---> simple while statement which loops till value of i is less that 10
do
echo "$n * $i = `expr $i \* $n`" ---> This is a syntax error bcoz value of n is never assigned
i=`expr $i + 1` ---> This line add's one to value of i
done ---> terminate while loop
Hope that explains you.

bash shell script concatenate string with period char

I am trying to create following string
Beta-3.8.0
but shell script always omits the . period char no matter what I do.
echo "$readVersion"
if [ -z $readVersion ]
then
echo "readVersion is empty"
exit 1
fi;
IFS=.
set $readVersion
newVersion=$(echo "$2 + 1" | bc)
newBranch="Beta-$1.$newVersion.$3"
echo $newBranch
prints:
3.8.0
Beta-3 9 0
I have also tried
newBranch='Beta-'$1'.'$newVersion'.'$3
or
newBranch="Beta-{$1}.{$newVersion}.{$3}"
although this seems printing the right value echo "$1.$newVersion.$3" why not variable doesnt work ?
I need the variable to use later on in the script...
You can save and restore the IFS once you are done.
oldIFS=$IFS
IFS=.
set $readVersion
newVersion=$(echo "$2 + 1" | bc)
IFS=$oldIFS
newBranch="Beta-$1.$newVersion.$3"
echo "$newBranch"
Or you can quote when printing:
echo "$newBranch"
The former is a better idea IMO since it conveys your intention and would make the rest of the code use the "correct" IFS. The latter just circumvents the problem.

Resources