Updating Array Value in For Loop Bash - arrays

I'm interested in updating an array element value within a for loop, but my update definition is wrong, since the output contain [counter].
Here is the code I have:
declare -a mem_set=(0 0 0 0 0 0 0)
counter=0
for i in "${domain_path[#]}"
do
cd $i
echo "$(pwd)"
for mLine in $(grep 'default.default.minmaxmemory.main' start_params.properties)
do
echo "$mLine"
done
l_bound="Xmx"
r_bound="m"
mem_set[counter]=$(echo "$mLine" | sed -e "s/.*${l_bound}//;s/${r_bound}.*//")
echo "$mem_set[counter]"
let counter=counter+1
done
The loop and the $(echo "$mLine" | sed -e "s/.*${l_bound}//;s/${r_bound}.*//") run fine, but I can't manage to get the right output. What is my update statement is missing? The output of it is 2048[counter]. Also, instead of using another counter counter in addition to i, is it possible to use i for mem_set array as well (both arrays have the same size)?
Thank you

Since feature requests to mark a comment as an answer remain declined, I copy the above solution here.
can you change echo "$mem_set[counter]" to echo "${mem_set[counter]}" and see if that prints out the right value? – 1_CR
thank you for your suggestion. Changing the format worked, so now I get the right output. – Simply_Me

In bash, you would access a variable with $.
Try,
counter=`expr $counter + 1`
or
counter=$(( counter + 1 ))

Related

bash - unable to echo array value

I have four cameras and want to store output from any of it in empty array and get output code from any array member.
# streams to check
streams=("rtsp://Streaming/Channels/01" "rtsp://Streaming/Channels/201" "rtsp://Streaming/Channels/301" "rtsp://Streaming/Channels/401")
# declare array for stream codes
declare -a outputcodes
for stream in "${streams[#]}"; do
streamoutput=$(timeout 20s ffprobe -v quiet -print_format json -show_streams $stream)
# get output code for each stream
streamresults=$(jq -r '.streams[0].index' <<< "$streamoutput")
# add stream result to array
outputcodes+=$streamresults
done
exit 0
# get first array member result
echo ${outputcodes[0]}
the problem is that echo ${outputcodes[0]} echo ${outputcodes} shows nothing
What's the problem ?
when i add echo $streamresults to for loop i'm getting correct results
0
0
0
0
setting outputcodes+=($streamresults) changes nothing
Bash version:4.2.46(2)-release
Tried to declare array in this way but same output:
declare -a outputcodes=()
I'm an idiot, had exit 0 before echoing array, once removed it all works.
Sorry for bothering

How to detect array start index by current shells (zsh/bash)?

We all know arrays in Bash are indexed from zero, and in zsh are indexed from one.
How can the script know it should use 0 or 1 if I can't ensure the running environment is bash, zsh or something else?
Expected code sample:
#!/bin/sh
detect_array_start_index(){
# ... how?
echo 1
}
ARR=(ele1 ele2)
startIndex=$(detect_array_start_index) # 0 or 1
for (( i=${startIndex}; i < ${#ARR[#]} + $startIndex; i++ )); do
echo "$i is ${ARR[$i]}"
done
I have a idea is find the index of the first value in a fixed array, I got this: Get the index of a value in a Bash array, but the accepted answer use bash variable indirection syntax ${!VAR[#]}, which is invalid in zsh.
Check the index 1 element of a two element array:
detect_array_start_index() {
local x=(1 0)
echo ${x[1]}
}
You can set the KSH_ARRAYS option in zsh to force array indexing to start at 0.
{ setopt KSH_ARRAYS || : ; } 2> /dev/null
ARR=(ele1 ele2)
for ((i=0; i < ${#ARR[#]}; i++ )); do
echo "$i is ${ARR[$i]}"
done
The command group and redirection allows the entire command to act as a no-op if executed from bash. The preceding code produces the same output in zsh and bash.

bash fill an array of integers from arguments and sort it

I looked everybody but I'm stuck with this code.
For example :
The user calls ./array.sh 3 5 6 2 1
I am supposed to sort (i thought bubble sort) and print the array sorted.
#! /bin/bash
tab=( $# )
define -i temp
for ((i = ${#tab[*]-1 ; i >= 0 ; i--)) ; do
for ((j = 0 ; i - 1; j++)) ; do
if [ ${tab[$i]} > ${tab[$i+1]} ] then
$temp = ${tab[$i+1]
${tab[$i+1]} = ${tab[$i]}
${$tab[$i]} = $temp
fi
done
echo ${tab[*]} #print the array
But bash is not happy with that, he keeps tellin me that I cannot assing values like that.
What do I do wrong ? Can you help me please ? I looked in a lot of places but there is no way to find the solution.
Thanks you in advance guys.
You cannot assign a value to a value (e.g. ${tab[$i+1]} = ${tab[$i]}); you must assign to a name or to an array element. Also, you may not have space on either side of the equals sign (=) in a bash assignment, except in numeric context.
And you dropped some closing braces.
And you misspelled "declare".
And you need a semicolon or newline between your if condition and your then.
And you didn't terminate your inner loop.
And you reference a non-existent array element via ${tab[$i+1]}.
And your inner loop has a constant as its termination condition.
And ${#tab[*]-1} incorrectly attempts to do math inside the braces delimiting the variable reference.
And you referenced the wrong index variable (consistently) in your inner loop.
And > is a redirection operator, not greater than, except in numeric context.
Once you clear up that multitude of errors, you end up with
#! /bin/bash
tab=( $# )
declare -i temp
for ((i = ${#tab[*]} - 1; i > 0 ; i--)) ; do
for ((j = 0 ; $j < $i; j++)) ; do
if [ ${tab[$j]} -gt ${tab[$j+1]} ]; then
temp=${tab[$j+1]}
tab[$j+1]=${tab[$j]}
tab[$j]=$temp
fi
done
done
echo ${tab[*]} #print the array
which actually works.
Your variable assignment syntax is all wrong.
First, you don't put $ before the variable being assigned.
Second, you must not have spaces around =.
So it should be:
temp=${tab[$i+1]}
tab[$i+1]=${tab[$i]}
tab[$i]=$temp
I understand that you are working on a class assignment or such and are restricted in how you are allowed to solve the problem. For those not so restricted, here is a simple solution using standard unix tools:
#!/bin/bash
( IFS=$'\n'; echo "$*" ) | sort -n
Sample usage:
$ script.sh 3 5 6 2 1
1
2
3
5
6
Explanation:
( IFS=$'\n'; echo "$*" )
This causes the command line arguments to be printed, one per line. This is in a subshell so that the assignment to IFS does not affect the rest of the script.
sort -n
-n tells sort to apply a numeric sort.

Bash array saving

The think is that I want to save something to an array in bash. The point is that I want one name of file for one array. So I don't know how much arrays I will have.
#!/bin/bash
declare -A NAMES
index=0
for a in recursive.o timeout.o print_recursive.o recfun.o
do
NAMES[$index]=$a
index=$((index+1))
echo ${NAMES[ $index ]}
done
When I run script with -x I can see that NAMES[$index], the index is not there represented as number so the whole thing doesn't work.
The error is at lines 7 and 8. Swap them and it will work.
When index have value 0 you set NAMES[0]=recursive.o, then increment index and print NAMES[1] which not set. And same thing for another elements. Because that there is no output.
Your loop should looks like this:
for a in recursive.o timeout.o print_recursive.o recfun.o
do
NAMES[$index]=$a
echo ${NAMES[$index]}
index=$((index+1))
done
The problem is in the following:
declare -A NAMES
This makes an associative array NAMES. Quoting from help declare:
Options which set attributes:
-a to make NAMEs indexed arrays (if supported)
-A to make NAMEs associative arrays (if supported)
You needed to say:
declare -a NAMES
May be you are trying to do this:
#!/bin/bash
declare -a NAMES
for a in recursive.o timeout.o print_recursive.o recfun.o; do
NAMES+=( "$a" )
done
for (( x=0; x<${#NAMES[#]}; x++ )); do
echo "Index:$x has Value:${NAMES[x]}"
done
Output:
Index:0 has Value:recursive.o
Index:1 has Value:timeout.o
Index:2 has Value:print_recursive.o
Index:3 has Value:recfun.o
Accessing the index which is not set is throwing it off.
NAMES[$index]=$a #Setting up an array with index 0
index=$((index+1)) #Incrementing the index to 1
echo ${NAMES[ $index ]} #Accessing value of index 1 which is not yet set

shell adding string to an array

I am having some trouble adding a string to an array within a loop. For some reason it always adds the same line. Here is my code:
declare -a properties
counter=0
while read line
do
if [[ ${line} == *=* ]]
then
properties[${counter}]=${line}
(( counter=counter + 1 ))
fi
done < ${FILE}
for x in ${!properties[#]}
do
echo "the value is $properties[x]"
done
For some reason each element in the array is the first line in the file. I must be doing something wrong, just not sure what.
Any help would be greatly appreciated
Try this script:
declare -a properties
while read line
do
[[ "${line}" == *=* ]] && properties+=("$line")
done < "${FILE}"
for x in "${properties[#]}"
do
echo "the value is "$x"
done
As #twalberg mentions in this comment, the problem is not in the top loop, but in the bottom one:
for x in ${!properties[#]}
do
echo "the value is $properties[x]"
done
Array references always need braces { ... } to expand properly.
For some reason each element in the array is the first line in the
file.
Not so. The array is correctly populated, but you need to change the reference to the array from:
echo "the value is $properties[x]"
to:
echo "the value is ${properties[x]}"
Just a simple oversight.
A much simpler way to add an element to an array is to simply use the syntax:
VARNAME+=("content")
Also, as written, your bug may be here:
(( counter=counter + 1 ))
It probably should be one of these three:
(( counter=$counter + 1 ))
counter+=1
counter=$[$counter+1]
counter=$(($counter + 1))
This KornShell (ksh) script worked fine for me. Let me know if anything.
readFileArrayExample.ksh
#! /usr/bin/ksh
file=input.txt
typeset -i counter=0
while read line
do
if [[ ${line} == *=* ]]; then
properties[${counter}]="${line}"
((counter = counter + 1))
echo "counter:${counter}"
fi
done < "${file}"
#echo ${properties[*]}
for x in "${properties[#]}"
do
echo "${x}"
done
readFileArrayExample.ksh Output:
#:/tmp #ksh readFileArrayExample.ksh
counter:1
counter:2
counter:3
a=b
a=1
b=1
#:/tmp #
input.txt
a-b
a+b
a=b
a=1
b=1
1-a

Resources