0

If there is a string:

[[some_str,another_str],[some_str,the_str],[some_str,the_str],[some_str,whatever_str]]

And I want output like this:

another_str: 1
the_str: 2
whatever_str:1

How could I do that?

2 Answers2

4
# read strings into an array, excluding [, ] and , characters
IFS='[],' read -r -a strings <<<'[[some_str,another_str],[some_str,the_str],[some_str,the_str],[some_str,whatever_str]]'

# store counts in an associative array
declare -A counts=()
for string in "${strings[@]}"; do
  [[ $string ]] || continue
  (( 'counts[$string]' += 1 ))
done

# iterate over that associative array and print counters
for string in "${!counts[@]}"; do
  echo "$string: ${counts[$string]}"
done
gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • Requires bash 4 or greater for associative arrays. Also there's some IFS/read/heredoc/herestring bug that was fixed in some bash 4+ version that may or may not be relevant here (I forget the details unfortunately). – Etan Reisner Oct 31 '14 at 14:01
  • The current version as edited (thanks, @gniourf_gnioruf) works back on 4.0.35, so I don't believe we're depending on any recent fixes here. – Charles Duffy Oct 31 '14 at 14:04
  • Looks like the issue I was thinking of was leaking `IFS` to the redirection and was a `4.2` bug fixed in `4.3`. So yes, this is fine. (For the record it was never my intent to question that fact.) – Etan Reisner Oct 31 '14 at 16:13
  • Interesting -- I hadn't heard about that bug; will try to keep it in mind. Thanks! – Charles Duffy Oct 31 '14 at 16:15
  • Not the best resource but something at least. http://stackoverflow.com/questions/24929819/ifs-change-with-bash-4-2 – Etan Reisner Oct 31 '14 at 16:17
0

If you were willing to use awk, you could do something like this:

$ awk -F] -vRS="," '!(NR%2){++a[$1]}END{for(i in a)printf "%s: %s\n",i,a[i]}' <<<"[[some_str,another_str],[some_str,the_str],[some_str,the_str],[some_str,whatever_str]]"
whatever_str: 1
another_str: 1
the_str: 2

Set the field separator to ] and the record separator to ,. Count the occurrence of every second record. After all records have been processed, print the results.

Tom Fenech
  • 72,334
  • 12
  • 107
  • 141