Decoding a string

Hi,

If my input string is

3a3b4c

then my result should be

aaabbbcccc

. Please guide me how to achieve this in a bash script.

Thanks

$ cat input
3a3b4c
4a5d2c
10a12b14c
3abc4xyz5pqr
$
$ perl -ne 'chomp;print$2x$1while(/(\d+)(\D+)/g);print"\n"' input
aaabbbcccc
aaaadddddcc
aaaaaaaaaabbbbbbbbbbbbcccccccccccccc
abcabcabcxyzxyzxyzxyzpqrpqrpqrpqrpqr
$

Thanks for your perl method. Out of interest, i want to accomplish in pure bash method.
Could you please suggest?
Thanks

@pandeesh
Please show is your best effort and happened when you tried your own bash script.

I have started writing the script:

############################RunLength_Decode###################################
#
#Implementatin of RunLength Decoding
#Written on:19March 11AM
#Author:Pandeeswaran
###############################################################################
#!/bin/bash
len=`echo $1|wc -c`
a=$1
for((i=0;i<=$len-1;i++))
do
ch=${a:$i:1}
echo $ch
if [ "${ch}" -eq "3" -o "${ch}" -eq "4" ]
then
res=${ch}
else
res=`echo "$res",`
fi
done
pandeeswaran@ubuntu:~/training$ bash RunLength_decode 3a
3
a
RunLength_decode: line 14: [: a: integer expression expected

RunLength_decode: line 14: [: : integer expression expected
pandeeswaran@ubuntu:~/training$ 

Please help me.
Thanks

 
if [ "${ch}" -eq "3" -o "${ch}" -eq "4" ]

Should be

 
if [ "${ch}" = "3" -o "${ch}" = "4" ]
 
OR 
 
if [ ${ch} -eq 3 -o ${ch} -eq 4 ]

= for comparing string
-eq for numbers

Thanks .. Is there any shortcut to check or 0 to 9.
Here I checked or 3 or 4. Without using multiple -o , is there any simple way to check for 0-9?
Thanks

You can use regular expression match

if [ "${ch}" =~ "[0-9]" ]

the match is not working as expected:

#!/bin/bash
len=`echo $1|wc -c`
a=$1
for((i=0;i<=$len-1;i++))
do
ch=${a:$i:1}
echo $ch
if [ "${ch}" =~ "[0-9]" ]
then
res=${ch}
else
res=`echo "$res",`
fi
done

pandeeswaran@ubuntu:~/training$ bash RunLength_decode 3a
3
RunLength_decode: line 14: [: =~: binary operator expected
a
RunLength_decode: line 14: [: =~: binary operator expected

RunLength_decode: line 14: [: =~: binary operator expected

Try with double brackets.. like this:

if [[ "${ch}" =~ "[0-9]" ]]

Which bash version you are using

there was a change between 3.1 and 3.2

if its 3.2 try

 
if [[ "${ch}" =~ [0-9] ]]

With out double quotes on regex.

Thanks Balasuri for correction :slight_smile:

@max_hammer: I don't think [ "$x" =~ [0-9] ] would work on bash 3.2 either.

I'm using GNU bash, version 3.2.25 and [ "$x" =~ [0-9] ] doesn't work. Regex matching is not supported by single square brackets.

if [[ "${ch}" =~ [0-9] ]];

does the trick

Thanks balajesuri for correction and information.

I am using ksh and single bracket works fine for ksh. :slight_smile:

Hi all,
as per my requirement i have splited the input into two parts:

############################RunLength_Decode###################################
#
#Implementatin of RunLength Decoding
#Written on:19March 11AM
#Author:Pandeeswaran
###############################################################################
#!/bin/bash
len=`echo $1|wc -c`
a=$1
for((i=0;i<=$len-1;i++))
do
ch=${a:$i:1}
if [[ "${ch}" =~ [0-9] ]];
then
res=`echo $res,${ch}`
else
res=`echo "$res",`
fi
done
Runs=`echo $res|sed -e "s/^,//"|tr -s ,|sed -e "s/.$//"`
echo $Runs
for((i=0;i<=$len-1;i++))
do
ch=${a:$i:1}
if [[ "${ch}" =~ [a-z] ]];
then
e=`echo $e,${ch}`
else
e=`echo "$e",`
fi
done
alph=`echo $e|sed -e "s/^,//"|tr -s ,|sed -e "s/.$//"|sed -e "s/,//"`
echo $alph

pandeeswaran@ubuntu:~/training$ bash RunLength_decode 3a4b3x3e
3,4,3,3
a,b,x,e
pandeeswaran@ubuntu:~/training$ 

Now i need to get "aaabbbbxxxeee".
How to proceed further? please guide me.
Thanks

Your code takes 0.02s on my machine!! I'm working on a server having 6 quad core cpu's each clocking 2.4 GHz and running on RHEL.

Try this. I don't claim it to be the most efficient. But still give it a try:

#! /bin/bash

len=$(($(echo $1 | wc -c) - 1))
a=$1
for ((i=0; i<=$len; i++))
do
    ch=${a:$i:1}
    if [[ "${ch}" =~ [0-9] ]]
    then
        times=$ch
    else
        for ((j=1; j<=$times; j++))
        do
            echo -e "$ch\c"
        done
    fi
done
# ./test.sh 3a4b3x3e
aaabbbbxxxeee

But the above one will not address if we have input such as :

12a45r234p
#! /bin/bash

shopt -s extglob

x=$1
while [ ${#x} -gt 0 ]
do
    num=${x%%[a-zA-Z]*}; x=${x##+([0-9])}
    str=${x%%[0-9]*}; x=${x##+([a-zA-Z])}
    for ((i=1; i<=$num; i++))
    do
        echo -e "$str\c"
    done
done
echo
[root@host ~]# ./test.sh 10ab11cd12ef
ababababababababababcdcdcdcdcdcdcdcdcdcdcdefefefefefefefefefefefef
[root@host ~]# ./test.sh 3a4b5c
aaabbbbccccc
[root@host ~]# ./test.sh 10hello12world
hellohellohellohellohellohellohellohellohellohelloworldworldworldworldworldworldworldworldworldworldworldworld

Just out of curiosity, what is the real commercial scenario where you're requiring something like this?

Great man!
This is not an actual commercial scenario !
Just I am trying In my Interest