1

This is a similar question to this one

I want to do the word count but this time, using an array.

For example, I have the following IPs inside a bash array called IPS.

IPS=("1.1.1.1" "5.5.5.5" "3.3.3.3" "1.1.1.1" "2.2.2.2" "5.5.5.5" "1.1.1.1")

If I read its contents:

user@server~$ "${IPS[*]}"
1.1.1.1 5.5.5.5 3.3.3.3 1.1.1.1 2.2.2.2 5.5.5.5 1.1.1.1

I would like to have something similar to this:

3 1.1.1.1
2 5.5.5.5
1 3.3.3.3
1 2.2.2.2
Geiser
  • 121
  • 6

2 Answers2

3

try:

printf '%s\n' "${IPS[@]}" |sort |uniq -c |sort -rn |sed 's/^ *//'
3 1.1.1.1
2 5.5.5.5
1 3.3.3.3
1 2.2.2.2

related:

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
αғsнιη
  • 40,939
  • 15
  • 71
  • 114
1

You can use an associative array to store the different IPS as keys which will increment when iterating over the IPS array.

#!/bin/bash
IPS=("1.1.1.1" "5.5.5.5" "3.3.3.3" "1.1.1.1" "2.2.2.2" "5.5.5.5" "1.1.1.1")
declare -A arr
for ip in ${IPS[@]};
do
        ((arr[${ip}]++))
done
for k in ${!arr[@]};
do
        echo "${arr[$k]} $k"
done | sort -rn
Lambert
  • 12,495
  • 2
  • 26
  • 35
  • Note that that `((arr[${ip}]++))` is an _arbitrary command execution_ vulnerability if the contents of `$ip`/`$IPS` is not under your control (try for instance `ip='$(uname>&2)x' bash -c 'typeset -A arr; ((arr[${ip}]++))'`). You'd want `arr[$ip]=$((${arr[$ip]} + 1))` here to avoid it. – Stéphane Chazelas Sep 30 '19 at 12:25