Solaris scripting problem with ksh88

Hello,

I want to pick a random element from a list, and created these 2 lines, which work very well in ksh93. Unfortunately, I get this "bad substitution" message in ksh88.

I'm wondering if there's an equivalent to the second line of my script.. or if I have to install ksh93 to make this work.

Here are my lines:

MATRICE="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@;:[].{}+=<>#|()^&_0123456789"

PASSWD="${MATRICE:$(($RANDOM%${#MATRICE})):1}"

Thanks in advance

You may need to split up the logic to achieve this, or awk may do this for you. I did something very clumsy many years ago with this:-

echo "$arg"|awk '{print substr($1,1,1)}'`

Perhaps that can be adjusted to something more suitable. My stab is:-

((rand=$RANDOM%7))      # Generates number from 0 to 6
((rand=$rand+1))        # To get number from 1 to 7

PASSWD=`echo $MATRICE $rand|awk '{print substr($1,$2,1)}'`

..... but I'm not saying that this is anywhere near the best :o

I hope that this helps though,
Robin

1 Like

Not sure if this works in ksh88 as I can't test it:

echo $((RANDOM%${#MATRICE})) | awk -vM="$MATRICE" 'BEGIN {n=split (M, T, "")} {print T[$1]}'

And, it might not be the most efficient approach if you want to use it for e.g. lengthy passwords...

EDIT: Try

PWLEN=25
while ((++I < PWLEN)); do echo $((RANDOM%${#MATRICE})); done | awk -vM="$MATRICE" 'BEGIN {n=split (M, T, "")} {printf "%s", T[$1]} END {printf "\n"}'
Z7{6M5<2Z6Z6691gcq[k0Z6p

Thanks!! This works great, and I certainly don't mind if it's not very efficient :slight_smile:

I tried the edited code, but it's not working. Do I need to initialize I=0?

MATRICE="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@;:[].{}+=<>#|()^&_0123456789"
I=0
PWLEN=25
while ((++I < $PWLEN)); do echo $((RANDOM%${#MATRICE})); done | awk  -vM="$MATRICE" 'BEGIN {n=split (M, T, "")} {printf "%s", T[$1]} END  {printf "\n"}'

What's the output of that while loop with the pipe to awk removed?

unset I
while ((++I < PWLEN)); do echo $((RANDOM%${#MATRICE})); done
48
86
63
75
46
3
74
43
87
44
62
83
3
43
39
82
18
49
89
13
14
5
90
8

It works properly if I run the commands manually or if I put the commands in a file:

./test.ksh
9
31
25
38
72
91
81
52
51

If I add "#!/bin/ksh" at the beginning of my script, I get this error:

./test.ksh
./test.ksh[5]: ++I < 10: bad number

Here's the inside of the script

#!/bin/ksh
MATRICE="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@;:[].{}+=<>#|()^&_0123456789"
unset I
PWLEN=10
while ((++I < $PWLEN)); do echo $((RANDOM%${#MATRICE})); done

I would turn MATRICE into an array with one character per array element. Then you just pick a random index into the array. This will work with all versions of ksh and it will be very fast.

Might I also suggest that using @ & # is a bad idea. Some operating systems and perhaps applications do not accept these characters all the time. HP-UX, for one, treats the @ as an end-of-field and therefore the password is truncated at that point.

I'm not sure what Solaris may do at various versions, or what your application may do if you are passing this password into that instead.

Robin

ksh88 does not have the full implementation of (( )) .
You can rewrite the bash-3/ksh93 style

I=0; while ((++I < PWLEN)); do echo $I; done

like this

I=1; while ((I < PWLEN)); do echo $I; ((I=I+1)); done

---------- Post updated at 05:09 PM ---------- Previous update was at 04:40 PM ----------

A straight translation:

PASSWD=`expr "$MATRICE" : ".\{$(($RANDOM%${#MATRICE}))\}\(.\)"`

Expert question: why can the ` ` not be a $(( )) ?