linux print variable vaule in foreach loop a1,a2,a3 - linux

I have a an old csh script (which hopefully I have time to rewrite in perl) which has a series of variables wmr1, wmr2 ... wmr24. What I would like to do is echo the values of each variable using a foreach loop eg
foreach i(`seq 1 24`)
echo ${wmr$i}
end
Can this be done in csh or using a perl one liner (using a symbolic refernce?)? I am not sure how to combine the integer $i with wmr and output the value of $wmr1 $wmr2 etc. echo ${wmr$i} in the loop gives me the error Missing }.

You can try this
foreach i (`seq 1 24`)
eval 'echo $wm'$i
end
The eval statement will evaluate the string given to it.
So replace echo with any other command you may want to use.

Related

Get variable name while iterating over array in bash

What I have is an array with some variables. I can iterate to get the values of those vars but what I need is actually their names (values will be used elsewhere).
Going with var[i] won't work cause I will have different names. I guess I could workaround this by creating another array with the names - something similar to this:
Getting variable values from variable names listed in array in Bash
But I'm wondering if there is a better way to do this.
var1=$'1'
var2=$'2'
var3=$'3'
Array=( $var1 $var2 $var3)
for ((i=0; i<${#Array[#]}; i++))
do
echo ${Array[i]}
done
Is:
>1
>2
>3
Should be:
>var1
>var2
>var3
It sounds like you want an associative array.
# to set values over time
declare -A Array=( ) || { echo "ERROR: Need bash 4.0 or newer" >&2; exit 1; }
Array[var1]=1
Array[var2]=2
Array[var3]=3
This can also be assigned at once:
# or as just one assignment
declare -A Array=( [var1]=1 [var2]=2 [var3]=3 )
Either way, one can iterate over the keys with "${!Array[#]}", and retrieve the value for a key with ${Array[key]}:
for var in "${!Array[#]}"; do
val="${Array[$var]}"
echo "$var -> $val"
done
...will, after either of the assignments up top, properly emit:
var1 -> 1
var2 -> 2
var3 -> 3
What about this solution?
#!/bin/bash
var1=$'1'
var2=$'2'
var3=$'3'
Array=( var1 var2 var3 )
for var in "${Array[#]}"; do
echo "$var = ${!var}"
done
The idea just consists in putting your variable names in the array, then relying on the indirection feature of Bash.
But as pointed out by #CharlesDuffy, the use of associative arrays sounds better adapted to the OP's use case.
Also, this related article may be worth reading: How can I use variable variables… or associative arrays?

How to iterate over the arguments of type string in the bash script?

An argument is passed to bash script from outside and is read within bash file. Looks like as follows:
#following is the point from where the argument is passed to config.sh
controller.vm.provision :shell, path: 'shell/config.sh', keep_color: true, privileged: false, :args => ip
inside the config.sh reading the argument. The argument "ip" is somewhat like following:
ip = "10.12.153.26" "10.12.153.25" "10.12.153.24"
Now i want to iterate over the above argument inside the bash. so doing as follows:
array=($1) //please note $1="10.12.153.26" "10.12.153.25" "10.12.153.24"
for i in ${array[#]}
do
echo $i //it is iterated only once and output is "10.12.153.26" "10.12.153.25" "10.12.153.24"
done
So the output i am getting only once and is complete argument as it is but i want it to get displayed one by one so, that i can even use the single value separately for some other purpose. So, please suggest how can i have this?
If you want to split the value on spaces, you can do like this:
set -- $1
for i; do
echo $i
done
If the value of $i is "10.12.153.26" "10.12.153.25" "10.12.153.24",
then this will output:
"10.12.153.26"
"10.12.153.25"
"10.12.153.24"
To get rid of the double-quotes, you could use parameter expansion:
set -- $1
for i; do
echo ${i//\"/}
done

How do you compare the value of an array to a variable in bash script?

I'm practicing bash and honestly, it is pretty fun. However, I'm trying to write a program that compares an array's value to a variable and if they are the same then it should print the array's value with an asterisk to the left of it.
#!/bin/bash
color[0]=red
color[1]=blue
color[2]=black
color[3]=brown
color[4]=yellow
favorite="black"
for i in {0..4};do echo ${color[$i]};
if {"$favorite"=$color[i]}; then
echo"* $color[i]"
done
output should be *black
There's few incorrect statements in your code that prevent it from doing what you ask it to. The comparison in bash is done withing square brackets, leaving space around them. You correctly use the = for string comparison, but should enclose in " the string variable. Also, while you correctly address the element array in the echo statement, you don't do so inside the comparison, where it should read ${color[$i]} as well. Same error in the asterisk print. So, here a reworked code with the fixes, but read more below.
#!/bin/bash
color[0]=red
color[1]=blue
color[2]=black
color[3]=brown
color[4]=yellow
favorite=black
for i in {0..4};do
echo ${color[$i]};
if [ "$favorite" = "${color[$i]}" ]; then
echo "* ${color[$i]}"
fi
done
While that code works now, few things that probably I like and would suggest (open to more expert input of course by the SO community): always enclose strings in ", as it makes evident it is a string variable; when looping an array, no need to use index variables; enclose variables always within ${}.
So my version of the same code would be:
#!/bin/bash
color=("red" "blue" "black" "brown" "yellow")
favorite="black"
for item in ${color[#]}; do
echo ${item}
if [ "${item}" = "${favorite}" ]; then
echo "* $item"
fi
done
And a pointer to the great Advanced Bash-Scripting Guide here: http://tldp.org/LDP/abs/html/

CSV Bash loop Issue with Variables

I have a csv file which im trying to loop through with the purpose to find out if an User Input is found inside the csv data. I wrote the following code which sometimes works and others doesn't. It always stops working when I try to compare to a 2+ digit number. It works OK for numbers 1 through 9, but once u enter lets say 56 , or 99 or 100, it stops working.
the csv data is comma delimited, i have about 300 lines they are just like this.
1,John Doe,Calculus I,5.0
1,John Doe,Calculus II,4.3
1,John Doe,Physics II,3.5
2,Mary Poppins,Calculus I,3.7
2,Mary Poppins,Calculus II,4.7
2,Mary Poppins,Physics I,3.7
Data is just like that, all the way down until ID #100 for a total of 300 lines. Both the sh file and csv file are in the same folder, I'm using a fresh installation of Ubuntu 12.04.3, using gedit as the text editor.
I tried Echoing the variables ID and inside the IF conditionals but it doesn't behave the way it should when testing for the same value. Could someone point me out in the right direction. Thanks
Here's the code:
#s!/bin/bash
echo "enter your user ID";
read user;
INPUT_FILE=notas.csv
while IFS="," read r- ID name asignature final;
do
if [$ID = $user]; then
userType=1;
else
userType=2;
fi
done < notas.csv
Well, your code as written has a few issues.
You have r- instead of -r on the read line - I assume that's a typo not present in your actual code or you wouldn't get very far.
Similarly, you need space around the [...] brackets: [$ID is a syntax error.
You need to quote the parameter expansions in your if clause, and/or switch bracket types. You probably make it a numeric comparison as #imp25 suggested, which I would do by using ((...)).
You probably don't want to set userType to 2 in an else clause, because that will set it to 2 for everyone except whoever is listed last in the file (ID 100, presumably). You want to set it to 2 first, outside the loop. Then, inside the loop when you find a match, set it to 1 and break out of the loop:
userType=2
while IFS=, read -r ID name asignature final; do
if (( $ID == $user )); then
userType=1;
break
fi
done < notas.csv
You could also just use shell tools like awk:
userType=$(awk -F, -vtype=2 '($1=="'"$user"'") {type=1}; END {print type}' notas.csv)
or grep:
grep -q "^$user," notas.csv
userType=$(( $? + 1 ))
etc.
You should quote your variables in the if test statement. You should also perform a numeric test -eq rather than a string comparison =. So your if statement should look like:
if [[ "$ID" -eq "$user" ]]

Shell Programming: Access Element of List

It is my understanding that when writing a Unix shell program you can iterate through a string like a list with a for loop. Does this mean you can access elements of the string by their index as well?
For example:
foo="fruit vegetable bread"
How could I access the first word of this sentence? I've tried using brackets like the C-based languages to no avail, and solutions I've read online require regular expressions, which I would like to avoid for now.
Pass $foo as argument to a function. Than you can use $1, $2 and so on to access the corresponding word in the function.
function try {
echo $1
}
a="one two three"
try $a
EDIT: another better version is:
a="one two three"
b=( $a )
echo ${b[0]}
EDIT(2): have a look at this thread.
Using arrays is the best solution.
Here's a tricky way using indirect variables
get() { local idx=${!#}; echo "${!idx}"; }
foo="one two three"
get $foo 1 # one
get $foo 2 # two
get $foo 3 # three
Notes:
$# is the number of parameters given to the function (4 in all these cases)
${!#} is the value of the last parameter
${!idx} is the value of the idx'th parameter
You must not quote $foo so the shell can split the string into words.
With a bit of error checking:
get() {
local idx=${!#}
if (( $idx < 1 || $idx >= $# )); then
echo "index out of bounds" >&2
return 1
fi
echo "${!idx}"
}
Please don't actually use this function. Use an array.

Resources