5

I have looked at the question How to count number of words from String using shell on SO, which explains how to count words inside a variable.

But this only counts one word inside my variable so I have no idea how to fix it.

I have the following variables:

vmfarm1=(host1.com host2.com host3.com host4.com )
maximus=(host11.com host 12.com host 13.com)
firefly=(host5.com)

I need to find a way to count all the host names into a number inside the variables.

After this, the number inside that was counted, have to be used as a variable in this line.

I have tried:

echo "$input" | wc -w
printf ' \n|/4.vmfarm1 ' >>  textfile.txt

I have to write the 4 above by myself to the number and I need it to be done automatically, this is why I need a variable.

10

Given an array arr, its length (number of elements) is given by ${#arr[@]}.

Using this with your vmfarm1 array:

printf ' \n|/%d.vmfarm1 ' "${#vmfarm1[@]}" >>textfile.txt
| improve this answer | |
9

To print the number of elements in an array variable in various shells with array support:

  • csh/tcsh/zsh/rc/es/akanga: echo $#array
  • ksh¹/bash¹/zsh: echo "${#array[@]}"
  • fish: count $array
  • yash: echo "${array[#]}"
  • Bourne/POSIX shells (where the only array is "$@"): echo "$#"

Now for the number of whitespace delimited words in all the elements of an array variable, that's where you may want to use wc -w, but you'd need to feed it the content of all the elements separated by at least one white space for instance with:

printf '%s\n' $array:q | wc -w        # csh/tcsh
printf '%s\n' "${array[@]}" | wc -w   # ksh/bash/zsh/yash
printf '%s\n' $array | wc -w          # fish/zsh/rc/es/akanga
printf '%s\n' "$@" | wc -w            # Bourne/POSIX

Or you could do the splitting of the elements into further whitespace-delimited words and count them in the shell itself.

  • csh/tcsh (split on SPC/TAB/NL)

    (set noglob; set tmp=($array); echo $#tmp)
    
  • ksh/bash/yash ($IFS splitting, SPC/TAB/NL by default)

    (set -o noglob; set -- ${array[@]}; echo "$#")
    
  • zsh ($IFS splitting, SPC/TAB/NL/NUL by default)

    echo ${#${=array}}
    
  • rc/es ($ifs splitting):

    tmp = `{echo $array}
    echo $#tmp
    
  • fish (counts all sequences of non-whitespace (according to PCRE) characters):

    count (string match -ar -- '\S+' $array)
    
  • Bourne/POSIX ($IFS splitting):

    (set -f; set -- $@; echo "$#")
    

¹ note that given that ksh/bash arrays are sparse and have indices that start at 0 instead of 1 in every other shell, that number will generally not be the same as the maximum index in the array

| improve this answer | |
3

In Bash and ksh, expanding an array as if it was a normal string variable, gives the first element of the array. That is, $somearray is the same as ${somearray[0]}. (*)

So,

somearray=(foo bar doo)
echo "$somearray"
echo "$somearray" | wc -w

prints foo and 1, since foo is only one word. If you had somearray=("foo bar doo" "acdc abba") instead, then the wc would show three words.

You'll need to use "${somearray[@]}" to expand all elements of the array as distinct shell words (arguments), or "${somearray[*]}" to expand them as a single shell word, joined with spaces (**)

In any case, note that the number of elements in an array, and the number of words (in the wc -w or the human language sense) are not the same, see below. Use "${#somearray[@]}" to get the number of elements in the array.

somearray=("foo bar doo" "acdc abba")
echo "${#somearray[@]}"                # 2 elements, that contain
echo "${somearray[@]}" | wc -w         # 5 whitespace separated words in total

(*) ignoring sparse and associative arrays for now.

(**) assuming default IFS.

| improve this answer | |
  • 1
    Beware that first element of an array is ambiguous with ksh and bash as their arrays are space. $array expands to ${array[0]} or the empty string if the array has no element of index 0. For the first element of the array, you actually need ${array[@]:0:1}. – Stéphane Chazelas May 15 '18 at 10:59
2

vmfarm1, maximus and firefly are not just variables, these are arrays.

Use the proper syntax: ${#vmfarm1[@]} is the number of entries in your array.

| improve this answer | |
0

This may be not smart, but I think you can get number of hosts in array.

vmfarm1=(host1.com host2.com host3.com host4.com)
#maximus=(host11.com host12.com host13.com)
#firefly(host5.com)
COUNT=0

for i in ${vmfarm1[@]};
do
    HOSTCOUNT=`echo $i |wc -l`
    COUNT=$((COUNT + HOSTCOUNT))
done

printf "vmfarm1:%2d\n" $COUNT

Thanks

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.