-2

I have an exercise in which I have to get a string from the user read str and to print the number of times which the last character of this string is being repeated.

For example, the string is: ab2aa2b122 and the output will be : 4 because 2 is being repeated 4 times in the string.

My problem is to divide the string into single characters. I want that every character will be separated from the other character by space " " or by a \n in order to use the tr command and uniq command.

I have to use uniq and sort commands, in order to use these I have to split the characters, which means that every character must be separated by space or by \n.

Chris Seymour
  • 83,387
  • 30
  • 160
  • 202
user1923376
  • 51
  • 1
  • 1
  • 4
  • Using GNU sed: `sed 's/\B/ /g' <<<"$string"` or `sed 's/\B/\n/g' <<<"$string"` might be a start. – potong Dec 22 '12 at 14:06

5 Answers5

1

A 100% pure bash solution:

read -r -p "Enter your string: " a
l=${a:(-1)}
b=${a//[^$l]/}
n=${#b}
echo "Last character is \`$l' and is repeated $n times in the string \`$a'"

No loop, no external process, nothing!

As a one-liner (to show it's really short, and probably the shortest possible!):

echo "ab2aa2b122"|{ read -r a;b=${a//[^${a: -1}]/};echo ${#b};}

Edit

Explanations of the first version (the second one is exactly the same, but suited for a code-golf contest).

  • First line line reads user input and stores that input in variable a.
  • l=${a:(-1)} will store the last character of a in l. More generally, ${a:i:j} expands to the substring of a starting at index i, of length j. When i=-1, it expands to the last character.
  • Parameter expansion is used in the next line: ${a//P/R} will expand to a withall the P's replaced by R. Here, R is empty, and P is [^$l], so this matches all characters distinct from l. Bottom line: ${a//[^$l]/} expands to a where all the characters different from the last are deleted. So we're left with just 2222 in your case.
  • ${#b} expands to the size of b (here, its length). So we're done!
gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104
  • wow thanks, may you please tell me what's the first solution is doing? It's an extended regular expression solution, right? I would be very thankful if you would explain abit. thanks! – user1923376 Dec 22 '12 at 11:12
  • @user1923376 Added some explanation. I hope it will help you. – gniourf_gniourf Dec 22 '12 at 11:19
  • thank you very much! If ill have any more question, may I ask them from you? Thanks! – user1923376 Dec 22 '12 at 11:26
  • +1 for the substitution stuff, really clever – etuardu Dec 22 '12 at 11:28
  • Sorry, but I have another question.. I may not actually use this way, because, we still didn't learn it (Iv'e just checked), so, I actually have to split all characters as I said in the description up. Which means that every character must be seperated. May you give me a solution for this? (You may just tell how to seperate them)- I actually have to use sort and uniq commands. Again- I apologize, and very thankful to you help! – user1923376 Dec 22 '12 at 11:30
  • @user1923376 skwllsp's answer has a possibility to separate the characters from each other (but it's forking the external process `sed`). – gniourf_gniourf Dec 22 '12 at 11:38
  • Yes, that's the problem, they are using sed, and I still didn't learn it.. :( – user1923376 Dec 22 '12 at 11:40
  • @user1923376 Then what have you learnt so far? What are you allowed to use? – gniourf_gniourf Dec 22 '12 at 11:42
  • Iv'e learnt basic commands such as cat,cut,tr,sort,uniq,for and while loops,if, cp,wc,input-output (>|),abit of globe style and extended regular expressions (egrep..) but I'm allowed to use egrep and Extended reg expressions, and globe style in the current excercise. Thanks! – user1923376 Dec 22 '12 at 11:47
  • @user1923376 I wrote another answer. Hope it'll help. – gniourf_gniourf Dec 22 '12 at 11:56
0

Not sure that you can use sed in your exercise, but with sed it can be done like this:

bash-3.1$ PPP=`echo ab2aa2b122 | sed 's/\(.\)/\1 /g'`
bash-3.1$ echo $PPP
a b 2 a a 2 b 1 2 2
  • Iv'e learn basic commands such as cat,cut,tr,sort,uniq,for and while loops,if, cp,wc,input-output (>|),abit of globe style and extended regular expressions (egrep..) but I'm allowed to use egrep and Extended reg expressions, and globe style here, lso no sed.. – user1923376 Dec 22 '12 at 11:51
0

awk one-liner:

kent$  echo "ab2aa2b122"|awk  'BEGIN{FS=""}{for(i=1;i<=NF;i++)a[$i]++;print "last char "$NF" : "a[$NF]" times";}'
last char 2 : 4 times

if you just want to get the number "4":

kent$  echo "ab2aa2b122"|awk  'BEGIN{FS=""}{for(i=1;i<=NF;i++)a[$i]++;print a[$NF]}'
4
Kent
  • 189,393
  • 32
  • 233
  • 301
  • Guys, thanks for all your comments, but I can't use all these ways (Cause I still didn't learn it). I have to use uniq and sort commands, in order to use these- I have to split the characters, which means that every character must be seperated by space or by \n. Thank you! – user1923376 Dec 22 '12 at 11:37
0

From the OP:

My problem is to divide the string into single characters. I want that every character will be seperated from the other character by space (" ") or by a \n (next line)-in order to use the tr command and uniq command.

From a comment left as a comment to my other answer:

Iv'e learnt basic commands such as cat,cut,tr,sort,uniq,for and while loops,if, cp,wc,input-output (>|),abit of globe style and extended regular expressions (egrep..) but I'm allowed to use egrep and Extended reg expressions, and globe style in the current excercise. Thanks!

To "divide" your string using grep:

  • Using a terrible echo-pipe and subshell:

    echo "$string" | grep -o '.'
    
  • Using a here string:

    grep -o '.' <<< "$string"
    

Hope this helps!

gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104
0

Only using wc, cut and tr:

#/bin/bash

input="ab2aa2b122"

length=$(wc -c <<< $input)

last=$(cut -c $((length-1)) <<< $input)

tr -dc $last <<< $input | wc -c

wc -c counts the number of characters in the string.

cut -c $len-1 gets the last character in the string

tr -dc $last removes all the characters that aren't the last (i.e 2) leaving the string 2222 and then use wc -c to count the length again.

./script.sh 
4
Chris Seymour
  • 83,387
  • 30
  • 160
  • 202
  • Same algorithm as my answer `:-)` – gniourf_gniourf Dec 22 '12 at 13:12
  • @gniourf_gniourf reading the comments hopefully the use of just these commands is okay, I've been racking my brains on how to split a string to separate characters with only the *allowed* tools but I don't think it's possible so `uniq` and `sort` are out the window. – Chris Seymour Dec 22 '12 at 13:18