Error in getting array length in bash after passing to function - arrays

What is wrong in this approach I can't get correct value of array length
#!/bin/bash
foo(){
val=$#
len=${#val[#]}
echo "Array contains: " $val
echo "Array length is: " $len
}
var=(1 2 3)
foo ${var[#]}
Output:
Array contains: 1 2 3
Array length is: 1

Change val=$# to val=("${#}") and you should be fine.
This answer in unix.stackexchange explains why:
You're flattening the input into a single value.
You should do
list=("${#}")
to maintain the array and the potential of whitespace in
arguments.
If you miss out the " then something like ./script.sh "a b" 2 3 4 will
return a length of 5 because the first argument will be split up

Related

Populate array in a for loop

I have an array of strings to pass through a script. The script is well-behaved, and will return error code 0 if the string "passes" and non-zero if it "fails." If the string passes, it should be included in a final array to be output or written to file or etc.
The problem I'm having is that the only item ending up in my final array is the first "passing" string.
#!/bin/bash
# validator.sh
if [[ $1 -le 10 ]]; then
exit 0
else
exit 1
fi
#!/bin/bash
# main.sh
numbers=(2 4 6 8 10 12 14 16)
keep=()
for n in ${numbers[#]}; do
if ./validator.sh $n; then
keep+=("$n")
fi
done
echo $keep
Running main.sh produces:
$ ./main.sh
2
but I expect 2 4 6 8 10
Unless you meant keep to be an array of matching elements, change:
keep+=("$n")
to
keep="$keep $n"
That would work with any Bourne compatible shell and is therefore better, if you're looking for BASH specific solution, the below will also work:
keep+="${n} "
If you DO want it to be an array, then in order to output all elements, you can use:
echo ${keep[#]}
As noted by #Jetchisel and #kamilCuk in the comments.
Since you wrote you want to output all elements or save them to a file, I had assumed you don't actually need an array here but perhaps you plan to use this data in other ways later:)

change array value while looping in bash

The code
SourceFolder[0]=""
SourceFolder[1]="inbound2"
SourceFolder[2]="inbound3"
for i in "${!SourceFolder[#]}"
do
if [ -z "${SourceFolder[$i]}"]; then
${SourceFolder[$i]} = "TEST"
fi
done
${SourceFolder[$i]} = "TEST" - doesn't work
it says
=: command not found
How to change value in current loop index in an array?
Because of the first space = is not interpreted as an assignment. There is a full explanation on So.
Btw ${SourceFolder[$i]} evaluate the array element, which is not what you want to do. For instance for the first one it is the empty string.
Replaces with SourceFolder[$i]=
You must change indexnumber in the your array:
ARRAYNAME[indexnumber]=value
ok, you have array is:
array=(one two three)
you can add count to your script for initialize and change element for array indexnumber, example:
#!/bin/bash
count=0
array=(one two three)
for i in ${array[#]}
do
echo "$i"
array[$count]="$i-indexnumber-is-$count"
count=$((count + 1))
echo $count
done
echo ${array[*]}
Result:
bash test-arr.sh
one
1
two
2
three
3
one-indexnumber-is-0 two-indexnumber-is-1 three-indexnumber-is-2

Bash Array - Cant get input from a loop in to my array correctly

I run this script as
script.sh 'abcdefghijk123456789!##$%^&' 'aaaa4444ged###'
it should be able to produce an array containing something like
1 1 1 1 15 15 15 15 7 5 23 23 23
with 12 indexes 0 - 11, but what i get is
1 1 1 1 1 5 1 5 1 5 1 5 7 5 2 3 2 3 2 3
with 20 indexes.
I want to populate a array with base numbers for a given char.
So i have a list of chars that we will be using in $startstring ie.
abcc5678% we can say that every char in $startstring is = to one char in the
$charset ie. abcd5678!%. This code finds what each $startstring char is equal
to $charset's index number. That information is what i am trying to capture in a
array. Mostly it works except a bug where instead of the whole number 10 getting
stored in decoded[1] what happens is the number 10 is split in to 1 and 0 and
then both are put in under separate indexes. So instead of a "1 10 1" and 3
indexes i end up with 4 indexes with "1 1 0 1". Im sure im just handling my
variables the wrong way but i searched and searched and now my brain is gonna
explode so i came here for some relief. or hope of it anyway. Can someone tell
me the proper way to insert digits in to this decoded[] array?
#!/bin/bash
#declare -i decoded
charset=$1
startstring=$2
start=$((${#charset}-1))
echo "Setting up CharMap to CharSet"
for i in $(eval echo {0..$start})
do
echo $i " = " ${charset:$i:1}
done
echo "Proving Chars Were Mapped Correctly."
start2=$((${#startstring}))
start3=$((${#charset}-1))
for i in $(eval echo {0..$start2})
do
for p in $(eval echo {0..$start3})
do
if [ "${startstring:$i:1}" == "${charset:$p:1}" ]
then
echo "found that" ${startstring:$i:1}"=" $p 'from the charmap.'
decoded+=$p #<--### I DONT THINK THIS IS WHAT I NEED ###
fi
done
done
##################Just trying to print my new array#########################
start4=$((${#decoded}-1))
echo 'Testing the array $decoded'
echo 'the var start4(length of $decoded) = '$start4
echo 'this number should equal ----------> '$start2
echo 'Printing out the $decoded array in a for loop'
for c in $(eval echo {0..$start4})
do
echo ${decoded[$c]} ###DOESNT WORK LIKE I THOUGHT# also tried echo ${decode:$c:1}
done
decoded+=$p appends $p as a string, not as an array entry. Essentially, you're creating the string "11111515151575232323" by appending all the index numbers together. (Actually, I get "00001414141464322222227" from your example, because of index bound problems. I'll let you worry about that...)
To store the decoded values as an array, set decoded to an empty array before the loop, and then use decoded+=("$p") to add $p as an element:
decoded=() # create an empty array
for i in $(eval echo {0..$start2})
do
for p in $(eval echo {0..$start3})
do
if [ "${startstring:$i:1}" == "${charset:$p:1}" ]
then
echo ${startstring:$i:1} "=" $p
decoded+=("$p") # append $p as a new array element
fi
done
done
Then, to get the size of the array (rather than a string length), use ${#decoded[#]}:
start4=$((${#decoded[#]}-1))

Bash Arrays - Couldn't extract the assigned variable from the array(2D)

I used the array assignment below in order to simulate a two dimensional array:
for((i=0;i<2;i++))
do
for((j=0;j<3;j++))
do
read TWOD$i[$j]
done
done < hi.txt
The file hi.txt contains these lines:
1
2
3
4
5
6
If I use echo ${TWOD0[2]}, I can print the value 2, but if I am using a variable for the first index, bash throws a syntax error bad substitution:
for((i=0;i<2;i++))
do
printf "%s\n" "${TWOD$i[2]}"
done
Is there any way to extract the elements from the array using a variable for the first index?
You can use indirect expansion:
row="TWOD$i[2]"
printf "%s\n" ${!row}

How to find the length of an array in shell?

How do I find the length of an array in shell?
For example:
arr=(1 2 3 4 5)
And I want to get its length, which is 5 in this case.
$ a=(1 2 3 4)
$ echo ${#a[#]}
4
From Bash manual:
${#parameter}
The length in characters of the expanded value of parameter is substituted. If parameter is ‘’ or ‘#’, the value substituted is the
number of positional parameters. If parameter is an array name
subscripted by ‘’ or ‘#’, the value substituted is the number of
elements in the array. If parameter is an indexed array name
subscripted by a negative number, that number is interpreted as
relative to one greater than the maximum index of parameter, so
negative indices count back from the end of the array, and an index of
-1 references the last element.
Length of strings, arrays, and associative arrays
string="0123456789" # create a string of 10 characters
array=(0 1 2 3 4 5 6 7 8 9) # create an indexed array of 10 elements
declare -A hash
hash=([one]=1 [two]=2 [three]=3) # create an associative array of 3 elements
echo "string length is: ${#string}" # length of string
echo "array length is: ${#array[#]}" # length of array using # as the index
echo "array length is: ${#array[*]}" # length of array using * as the index
echo "hash length is: ${#hash[#]}" # length of array using # as the index
echo "hash length is: ${#hash[*]}" # length of array using * as the index
output:
string length is: 10
array length is: 10
array length is: 10
hash length is: 3
hash length is: 3
Dealing with $#, the argument array:
set arg1 arg2 "arg 3"
args_copy=("$#")
echo "number of args is: $#"
echo "number of args is: ${##}"
echo "args_copy length is: ${#args_copy[#]}"
output:
number of args is: 3
number of args is: 3
args_copy length is: 3
Assuming bash:
~> declare -a foo
~> foo[0]="foo"
~> foo[1]="bar"
~> foo[2]="baz"
~> echo ${#foo[*]}
3
So, ${#ARRAY[*]} expands to the length of the array ARRAY.
in tcsh or csh:
~> set a = ( 1 2 3 4 5 )
~> echo $#a
5
In the Fish Shell the length of an array can be found with:
$ set a 1 2 3 4
$ count $a
4
This works well for me:
arglen=$#
argparam=$*
if [ $arglen -eq '3' ];
then
echo Valid Number of arguments
echo "Arguments are $*"
else
echo only four arguments are allowed
fi
For those who still searching a way to put the length of an array into a variable:
foo="${#ARRAY[*]}"

Resources