Consider the associative array below:
declare -A shapingTimes
shapingTimes=([0-start]=15 [0-stop]=21 [0-anotherkey]=foo)
shapingTimes+=([1-start]=4 [1-stop]=6 [1-anotherkey]=bar)
shapingTimes+=([2-start]=9 [2-stop]=11 [2-anotherkey]=blah)
Is there a way to find the total number of keys used per entry in an array? (Is this per 'index' in an array?)
For example, how to count: [start], [stop], [anotherkey] as = 3 keys?
At the moment I'm using the hardcoded value (3) from this code I found (as below) that does the job fine, but I'm wondering if this can be achieved dynamically?
totalshapingTimes=$((${#shapingTimes[*]} / 3))
I've found these variables that return various array aspects, but not the total number of keys.
echo "All of the items in the array:" ${shapingTimes[*]}
echo "All of the indexes in the array:" ${!shapingTimes[*]}
echo "Total number of items in the array:" ${#shapingTimes[*]}
echo "Total number of KEYS in each array entry:" #???
Desired output:
All of the items in the array: 21 6 11 blah 15 4 bar 9 foo
All of the indexes in the array: 0-stop 1-stop 2-stop 2-anotherkey 0-start 1-start 1-anotherkey 2-start 0-anotherkey
Total number of items in the array: 9
Total number of KEYS in each array entry: 3
declare -A shapingTimes
shapingTimes=([0-start]=15 [0-stop]=21 [0-anotherkey]=foo)
shapingTimes+=([1-start]=4 [1-stop]=6 [1-anotherkey]=bar)
shapingTimes+=([2-start]=9 [2-stop]=11 [2-anotherkey]=blah)
# output all keys
for i in "${!shapingTimes[#]}"; do echo $i; done
Output:
1-start
2-stop
1-stop
0-start
2-start
2-anotherkey
1-anotherkey
0-stop
0-anotherkey
# Leading numbers and "-" removed:
for i in "${!shapingTimes[#]}"; do echo ${i/#[0-9]*-/}; done
Output:
start
stop
stop
start
start
anotherkey
anotherkey
stop
anotherkey
# put shortend keys in new associative array
declare -A hash
for i in "${!shapingTimes[#]}"; do hash[${i/#[0-9]*-/}]=""; done
echo "${#hash[#]}"
Output:
3
Once you key your array names with -, there isn't a direct way to identify the count of occurrences of the string past the - character.
One way would be to use additional tools to identify the count. The "${!shapingTimes[#]}" prints all the keys of the array and sort -ut- k2 goes a unique sort based on the 2nd field following the - delimiter, which is piped to wc -l to get the line count.
printf '%s\n' "${!shapingTimes[#]}" | sort -ut- -k2 | wc -l
3
Same as #Cyrus's solution, but with no loop and no sub-shell:
#!/usr/bin/env bash
declare -A shapingTimes=(
[0-start]=15 [0-stop]=21 [0-anotherkey]=foo
[1-start]=4 [1-stop]=6 [1-anotherkey]=bar
[2-start]=9 [2-stop]=11 [2-anotherkey]=blah
)
# Populate simple array with keys only
declare -a shapingTimesKeys=("${!shapingTimes[#]}")
# Create associative array entries declaration string
# populated by prefix stripped keys
printf -v _str '[%q]= ' "${shapingTimesKeys[#]/#[0-9]*-/}"
# Declare the stripped keys associative array using
# the string populated just above
declare -A shapingTimesHash="($_str)"
printf 'Found %d keys:\n' "${#shapingTimesHash[#]}"
printf '%q\n' "${!shapingTimesHash[#]}"
It is easy to declare and store a number in array but problem is that the user gives input 1234 and i wanted to store this numbers as $array[0]=1, $array[1]=2, $array[2]=3, $array[3]=4 but instead what actually happens is that $array[0]=1234, $array[1]=null, $array[2]=null, $array[3]=null. I don't know how to store each number separately
#!/bin/bash
declare -a key
read -p "Enter the encryption key: " numbers
key=($numbers)
echo ${key[0]}
echo ${key[1]}
echo ${key[2]}
echo ${key[3]}.
Actual output:
Enter the encryption key: 1234
1234
null
null
null
Desired output:
Enter the encryption key: 1234
1
2
3
4
Thank you, in advance :)
There is also a possibility to use
key=(`grep -o . <<< "$numbers"`)
And you can access different letters in $numbers without creating an array by using a substring notation ${string:initial_index:length_of_substring}:
echo ${numbers:0:1}
echo ${numbers:1:1}
echo ${numbers:2:1}
echo ${numbers:3:1}
Seeing how you're using read so you already assume that there are no spaces in the key, you can do this:
#!/bin/bash
declare str
read -p "Enter the encryption key: " str
# replace each character with that character + space
spaced=$(echo "$str" | sed 's/\(.\)/\1 /g')
# without quotes, array elements will be each of the space-separated strings
numbers=( $spaced )
printf "array element %s\n" "${numbers[#]}"
Output:
Enter the encryption key: hello123
array element h
array element e
array element l
array element l
array element o
array element 1
array element 2
array element 3
You can try.
declare -a key
read -p "Enter the encryption key: " numbers
while read -n1 input; do
key+=("$input")
done < <(printf '%s' "$numbers")
printf '%s\n' "${key[#]}"
Imagine I created an array like this:
IFS="|" read -ra ARR <<< "zero|one|||four"
now
echo ${#ARR[#]}
> 5
echo "${ARR[#]}"
> zero one four
echo "${ARR[0]}"
> zero
echo "${ARR[2]}"
> # Nothing, because it is empty
The question is how can I replace the empty elements with another string?
I have tried
${ARR[#]///other}
${ARR[#]//""/other}
none of them worked.
I want this as output:
zero one other other four
To have the shell expansion behave, you need to loop through its elements and perform the replacement on each one of them:
$ IFS="|" read -ra ARR <<< "zero|one|||four"
$ for i in "${ARR[#]}"; do echo "${i:-other}"; done
zero
one
other
other
four
Where:
${parameter:-word}
If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.
To store them in a new array, just do so by appending with +=( element ):
$ new=()
$ for i in "${ARR[#]}"; do new+=("${i:-other}"); done
$ printf "%s\n" "${new[#]}"
zero
one
other
other
four
If you want to replace all empty values (actually modifying the list), you could do this :
for i in "${!ARR[#]}" ; do ARR[$i]="${ARR[$i]:-other}"; done
Which looks like this when indented (more readable I would say) :
for i in "${!ARR[#]}"
do
ARR[$i]="${ARR[$i]:-other}"
done
# Temporary array initialization
NEW=()
# Loop over the array, add only non-empty values to the new array
for i in "${ARR[#]}"; do
# Skip null items
if [ -z "$i" ]; then
continue
fi
# Add the rest of the elements to an array
NEW+=("${i}")
done
# Reinitialize your array
ARR=(${NEW[#]})
ahhh array and loops my weakest links. I was trying to create array depending on user input so
printf "%s\n" "how may array you want"
read value
after this i will ask what value user want to put on a array(this is the bit im stuck on)
i=1
while [ $i -le $value ]
do
echo "what value you want to put in array $i"
read number
echo $number >> array.db
i=$(( i+1 ))
echo
done
although this method works(i think) but i'm not too sure if i'm actually creating an array and putting value to that array.
you can expand arrays in bash dynamically. you can use this snippet
a=(); a[${#a[#]}]=${number}; echo ${a[#]}
The first statement defines an empty array. with the second (which you can use in your while loop) you insert a value at last elment position + 1, due to ${#a[#]} represents the length of a. the third statement just prints all elements in the array.
How do I create an array in unix shell scripting?
The following code creates and prints an array of strings in shell:
#!/bin/bash
array=("A" "B" "ElementC" "ElementE")
for element in "${array[#]}"
do
echo "$element"
done
echo
echo "Number of elements: ${#array[#]}"
echo
echo "${array[#]}"
Result:
A
B
ElementC
ElementE
Number of elements: 4
A B ElementC ElementE
in bash, you create array like this
arr=(one two three)
to call the elements
$ echo "${arr[0]}"
one
$ echo "${arr[2]}"
three
to ask for user input, you can use read
read -p "Enter your choice: " choice
Bourne shell doesn't support arrays. However, there are two ways to handle the issue.
Use positional shell parameters $1, $2, etc.:
$ set one two three
$ echo $*
one two three
$ echo $#
3
$ echo $2
two
Use variable evaluations:
$ n=1 ; eval a$n="one"
$ n=2 ; eval a$n="two"
$ n=3 ; eval a$n="three"
$ n=2
$ eval echo \$a$n
two
#!/bin/bash
# define a array, space to separate every item
foo=(foo1 foo2)
# access
echo "${foo[1]}"
# add or changes
foo[0]=bar
foo[2]=cat
foo[1000]=also_OK
You can read the ABS "Advanced Bash-Scripting Guide"
The Bourne shell and C shell don't have arrays, IIRC.
In addition to what others have said, in Bash you can get the number of elements in an array as follows:
elements=${#arrayname[#]}
and do slice-style operations:
arrayname=(apple banana cherry)
echo ${arrayname[#]:1} # yields "banana cherry"
echo ${arrayname[#]: -1} # yields "cherry"
echo ${arrayname[${#arrayname[#]}-1]} # yields "cherry"
echo ${arrayname[#]:0:2} # yields "apple banana"
echo ${arrayname[#]:1:1} # yields "banana"
Try this :
echo "Find the Largest Number and Smallest Number of a given number"
echo "---------------------------------------------------------------------------------"
echo "Enter the number"
read n
i=0
while [ $n -gt 0 ] #For Seperating digits and Stored into array "x"
do
x[$i]=`expr $n % 10`
n=`expr $n / 10`
i=`expr $i + 1`
done
echo "Array values ${x[#]}" # For displaying array elements
len=${#x[*]} # it returns the array length
for (( i=0; i<len; i++ )) # For Sorting array elements using Bubble sort
do
for (( j=i+1; j<len; j++ ))
do
if [ `echo "${x[$i]} > ${x[$j]}"|bc` ]
then
t=${x[$i]}
t=${x[$i]}
x[$i]=${x[$j]}
x[$j]=$t
fi
done
done
echo "Array values ${x[*]}" # Displaying of Sorted Array
for (( i=len-1; i>=0; i-- )) # Form largest number
do
a=`echo $a \* 10 + ${x[$i]}|bc`
done
echo "Largest Number is : $a"
l=$a #Largest number
s=0
while [ $a -gt 0 ] # Reversing of number, We get Smallest number
do
r=`expr $a % 10`
s=`echo "$s * 10 + $r"|bc`
a=`expr $a / 10`
done
echo "Smallest Number is : $s" #Smallest Number
echo "Difference between Largest number and Smallest number"
echo "=========================================="
Diff=`expr $l - $s`
echo "Result is : $Diff"
echo "If you try it, We can get it"
Your question asks about "unix shell scripting", but is tagged bash. Those are two different answers.
The POSIX specification for shells does not have anything to say about arrays, as the original Bourne shell did not support them. Even today, on FreeBSD, Ubuntu Linux, and many other systems, /bin/sh does not have array support. So if you want your script to work in different Bourne-compatible shells, you shouldn't use them. Alternatively, if you are assuming a specific shell, then be sure to put its full name in the shebang line, e.g. #!/usr/bin/env bash.
If you are using bash or zsh, or a modern version of ksh, you can create an array like this:
myArray=(first "second element" 3rd)
and access elements like this
$ echo "${myArray[1]}" # for bash/ksh; for zsh, echo $myArray[2]
second element
You can get all the elements via "${myArray[#]}". You can use the slice notation ${array[#]:start:length} to restrict the portion of the array referenced, e.g. "${myArray[#]:1}" to leave off the first element.
The length of the array is ${#myArray[#]}. You can get a new array containing all the indexes from an existing array with "${!myArray[#]}".
Older versions of ksh before ksh93 also had arrays, but not the parenthesis-based notation, nor did they support slicing. You could create an array like this, though:
set -A myArray -- first "second element" 3rd
You can try of the following type :
#!/bin/bash
declare -a arr
i=0
j=0
for dir in $(find /home/rmajeti/programs -type d)
do
arr[i]=$dir
i=$((i+1))
done
while [ $j -lt $i ]
do
echo ${arr[$j]}
j=$((j+1))
done
An array can be loaded in twoways.
set -A TEST_ARRAY alpha beta gamma
or
X=0 # Initialize counter to zero.
-- Load the array with the strings alpha, beta, and gamma
for ELEMENT in alpha gamma beta
do
TEST_ARRAY[$X]=$ELEMENT
((X = X + 1))
done
Also, I think below information may help:
The shell supports one-dimensional arrays. The maximum number of array
elements is 1,024. When an array is defined, it is automatically
dimensioned to 1,024 elements. A one-dimensional array contains a
sequence of array elements, which are like the boxcars connected
together on a train track.
In case you want to access the array:
echo ${MY_ARRAY[2] # Show the third array element
gamma
echo ${MY_ARRAY[*] # Show all array elements
- alpha beta gamma
echo ${MY_ARRAY[#] # Show all array elements
- alpha beta gamma
echo ${#MY_ARRAY[*]} # Show the total number of array elements
- 3
echo ${#MY_ARRAY[#]} # Show the total number of array elements
- 3
echo ${MY_ARRAY} # Show array element 0 (the first element)
- alpha
If you want a key value store with support for spaces use the -A parameter:
declare -A programCollection
programCollection["xwininfo"]="to aquire information about the target window."
for program in ${!programCollection[#]}
do
echo "The program ${program} is used ${programCollection[${program}]}"
done
http://linux.die.net/man/1/bash "Associative arrays are created using declare -A name. "
There are multiple ways to create an array in shell.
ARR[0]="ABC"
ARR[1]="BCD"
echo ${ARR[*]}
${ARR[*]} prints all elements in the array.
Second way is:
ARR=("A" "B" "C" "D" 5 7 "J")
echo ${#ARR[#]}
echo ${ARR[0]}
${#ARR[#]} is used to count length of the array.
To read the values from keybord and insert element into array
# enter 0 when exit the insert element
echo "Enter the numbers"
read n
while [ $n -ne 0 ]
do
x[$i]=`expr $n`
read n
let i++
done
#display the all array elements
echo "Array values ${x[#]}"
echo "Array values ${x[*]}"
# To find the array length
length=${#x[*]}
echo $length
A Simple way :
arr=("sharlock" "bomkesh" "feluda" ) ##declare array
len=${#arr[*]} #determine length of array
# iterate with for loop
for (( i=0; i<len; i++ ))
do
echo ${arr[$i]}
done
In ksh you do it:
set -A array element1 element2 elementn
# view the first element
echo ${array[0]}
# Amount elements (You have to substitute 1)
echo ${#array[*]}
# show last element
echo ${array[ $(( ${#array[*]} - 1 )) ]}