Use of variable name in shell script - shell

First of all I'm sorry for a probable bad title, but I don't even know what to call this.
I'm trying the following:
#!/bin/sh
VAR1="28-00000202070c"
VAR2="28-0000018776d3"
VAR3="28-0000033a6174"
for sensor in VAR1 VAR2 VAR3
do
echo "$sensor: $$sensor"
done
The expected output would be:
VAR1: 28-00000202070c
VAR2: 28-0000018776d3
VAR3: 28-0000033a6174
The real output is:
VAR1: 24038sensor
VAR2: 24038sensor
VAR3: 24038sensor
and the strange prefix number keeps growing...
VAR1: 24039sensor
VAR2: 24039sensor
VAR3: 24039sensor
...
I'd like to ask:
1) What are the correct terms/keywords that describe what I'm trying to do here
2) How to get to the expected output
Thanks,
Joaoabs

This is something that sh does not support, while bash does.
The correct syntax you should use is:
echo "$sensor ${!sensor}"
Test
$ cat a
#!/bin/bash <----- note I changed /bin/sh to /bin/bash
VAR1="28-00000202070c"
VAR2="28-0000018776d3"
VAR3="28-0000033a6174"
for sensor in VAR1 VAR2 VAR3
do
echo "$sensor ${!sensor}"
done
$ ./a
VAR1 28-00000202070c
VAR2 28-0000018776d3
VAR3 28-0000033a6174

Related

Can I concatenate aliases in YAML?

I would like to do something like:
opt-flags : &opt_flags -DCMAKE_BUILD_TYPE=Release
dbg-flags : &dbg_flags -DCMAKE_BUILD_TYPE=Debug
common-flags: &common -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON
# concatenate previous definitions to create composed definitions
dbg: *common *dbg_flags
opt: *common *opt_flags
This doesn't work directly. Is it possible to do something equivalent to this in YAML?
No you cannot do that, an alias replaces a complete node.
However if you are dealing with mappings, you can use the merge key language-independent type if your parser supports it to combine multiple sets of keys into a new mapping:
opt-flags : &opt_flags -DCMAKE_BUILD_TYPE=Release
dbg-flags : &dbg_flags -DCMAKE_BUILD_TYPE=Debug
common-flags: &common -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON
dbg:
<< : [*common_flags, *dbg_flags]
opt:
<< : [*common_flags, *opt_flags]
This however will make two entries each, and not concatenate the strings scalars that are anchored, and will need a program that can combine the multiple values, for which the ordering is not guaranteed.
Unfortunately in 2022 you still cannot concatenate or join aliases with other aliases or strings. For mappings, there is another syntax which works the same as "merge keys" (described in the accepted answer) but is less ambiguous and easier to read IMO. You can reference multiple anchors like so (this works in docker-compose btw):
x-foo: &foo
VAR1: value1
x-bar: &bar
VAR2: value2
foobar:
<<: *foo
<<: *bar
# foobar:
# VAR1: value1
# VAR2: value2
Also worth noting that you can nest anchors too:
x-foo: &foo
VAR1: value1
bar: &bar
VAR2: value2
foobar:
<<: *foo
bar:
<<: *bar
VAR3: value3
# foobar:
# VAR1: value1
# bar:
# VAR2: value2
# VAR3: value3

Read and Tokenize from a file in Bash

I want to read something from a file and tokenize it into several variables in Bash, but I'm not sure how.
Example:
Enter file path: foo/bar.txt
var1 = 'a'
var2 = 'b'
var3 = 'c'
var4 = 'd'
The contents of bar.txt would simply be "a,b,c,d". It would have to be a one line file. I was thinking of using grep somehow. Is there an easy way of doing this, or am I making things to complicated?
IFS=, read var1 var2 var3 var4 < bar.txt
Set field separator
Set input file
Set resultant variables

Unable to execute printf command by using formatter and argument variable

I am trying to store all the printf formatter and arguments into their own respective variables to be execute later. Example code:
var="abc123"
var2="def 456"
printfArgument=$var" "$var2
formatter="%-10s"
formatter2="%-10s"
printfFormatter=$formatter" "$formatter2"\n"
printf "$printfFormatter" $printfArgument
output:
abc123 def
456
It seems like the space in var2 causes the 456 to display improperly. Any way to fix it?
You're correct; the space in var2 is being used for word-splitting. printf is receiving 3 arguments after the format string: abc123, def, and 456. The first two fill the two format specifiers for the first line of output. Since there is a remaining argument, the format string is used again to produce the second line of output.
You need to use an array for printfArgument:
printfArgument=( "$var" "$var2" )
printf "$printfFormatter" "${printfArgument[#]}"
or just use var and var2 separately:
printf "$printfFormatter" "$var" "$var2"

Getting variable values from variable names listed in array in Bash

I'm trying to print values of multiple variables that are listed in a Bash array as evident in the minimal code example below.
#!/bin/bash
VAR1="/path/to/source/root"
VAR2="/path/to/target/root"
VAR3="50"
VARS=("VAR1" "VAR2" "VAR3")
for var in ${VARS[*]}; do
echo "value of $var is ${$var}"
done
This gives me an error
line 8: value of $var is ${$var}: bad substitution
I want the following output:
value of VAR1 is /path/to/source/root
value of VAR2 is /path/to/target/root
value of VAR3 is 50
My search on Google and SO was not very fruitful. Because of the indirection (i.e., var iterates over an array containing names of variables for which I want the values), I'm not able to precisely word my search. But any help is appreciated.
Use indirect reference as:
#!/bin/bash
VAR1="/path/to/source/root"
VAR2="/path/to/target/root"
VAR3="50"
VARS=("VAR1" "VAR2" "VAR3")
for var in ${VARS[*]}; do
echo "value of $var is ${!var}"
done
Output:
value of VAR1 is /path/to/source/root
value of VAR2 is /path/to/target/root
value of VAR3 is 50

Put print result in a variable or concat text variable

I have this
var1='hello'
var2='world'
I need helloworld in a variable. If I write
print $var1$var2 # prints "helloworld"
But when I write
var3=$var1$var2 # var3 is not "helloworld"
I tried
var3=$(print $var1$var2)
var3='$var1$var2'
Sure the only one I did not try is the good one but which one?
Edit after discovery curious thing:
If I do exactly as I wrote
var3=$var1$var2
print $var3 # prints "helloworld"
But in fact I wrote this to resume my problem with others variables, my own variables. The difference is that $var1 is the result of a awk command to extract this text from a file.
I try to explain:
myvar1 the variable I realy use is definite like this:
myvar1=awk -F"/" '${print $1}' $dir_path
And not like this
myvar1=world
That is only to ask you the question. I don't know why, but this seems to be important.
If I do the same thing with my variables that with var3=$var1$var2, it doe snot work. To get the right result with my variables, I have just found I must use:
myvar3=echo$myvar1$myvar2
print $myvar3 # gives the right result.
On the other hand, if I do
var3=echo$var1$var2
print $var3 # prints "echohelloworld"
How to explain that?
I am using Mac OS X, the command-line terminal and Zsh.
If you have
var1='hello'
var2='world'
Any of these will result in print $var3 # prints "helloworld"
var3="$var1$var2"
var4=$var1$var2
var5=$(print $var1$var2)
You should use the first one. You can verify either by printing the variables or by calling set:
$ print var3 # prints "helloworld"
$ set|grep var
var1=hello
var2=world
var3=helloworld
var4=helloworld
var5=helloworld
Your edit says, that you use: myvar1=awk -F"/" '{print $1} $dir_path. This line is missing a $():
myvar1=$(awk 'BEGIN { print "hello" }')
echo $myvar1 # prints hello

Resources