Reputation: 131
I am new to bash programming and I am struggling with arrays and how to operate with them. SCENARIO:
I have a variable called x which is composed of a group of IP's. This is the output when I echo $x from my script
182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 201.21.24.22 201.21.24.22 201.21.24.22
44.21.25.31 44.21.25.31 44.21.25.31 44.21.25.31
Then, I would like to know how many times each IP is repeated. The desired output would be:
15 182.100.67.59
4 44.21.25.31
3 201.21.24.22
I have tried the following
(IFS=" "; sort <<< "$x" ) | uniq -c
Output Note the first 1 on the output.
**1** 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 182.100.67.59 201.21.24.22 201.21.24.22 201.21.24.22 44.21.25.31 44.21.25.31 44.21.25.31 44.21.25.31
I am not seeing this, It should be pretty simple but I can't find the solution :( Thanks! And very great community!
Upvotes: 3
Views: 141
Reputation: 1882
Actually you don't have an array, per se; you have a string of numbers separated by spaces. If echo $x
gives the value you specify, this is the case and the answer is:
aips=( ${x} )
printf "%s\n" "${aips[@]}" | sort | uniq -c
This converts the string of numbers separated by spaces (IFS
) into the array aips
(the parens specify this is an array as opposed to a string), and then uses printf
with the behavior that it re-uses the format specification when there are more arguments than the format specification specifies, to print every element of the array (${aips[@]}
) followed by a newline, then sorts and uniq
s it.
Had this been a real array (e.g. x=( "182.100.67.59" "201.21.24.22" ...)
) the answer would be just the latter part:
printf "%s\n" "${x[@]}" | sort | uniq -c
15 182.100.67.59
3 201.21.24.22
4 44.21.25.31
Upvotes: 0
Reputation: 12337
Method 1:
Use tr
to replace spaces with newlines, followed by sort | uniq -c
:
tr ' ' '\n' <<<"$x" | sort | uniq -c
Method 2:
Use echo
with xargs -n1
to write the IPs one per line, followed by sort | uniq -c
. Note that xargs
is slower than tr
here, plus may have potential side effects, such as quote removal:
echo "$x" | xargs -n1 | sort | uniq -c
Upvotes: 3
Reputation: 5237
There's no need for arrays here.
A simple pipeline using grep
, sort
and uniq
will do the trick:
echo "$x" | grep -Eo '[0-9]+(\.[0-9]+){3}' | sort | uniq -c | sort -rn
Upvotes: 0