Random string generator in bash script does not count the number of given characters

I am trying to create a random character generator in a bash script in osx 10.8.5. The goal is to generate random character strings for the script generating salts for the wordpress file wp-config.php

. The snippet looks like this:

#!/bin/bash -e
read -p "Number of digits: " digits

function rand_char {
    take=$(($RANDOM % 88)); i=0; echo {a..z} {A..Z} {0..9} \, \; \. \: \- \_ \# \* \+ \~ \! \§ \$ \% \& \( \) \= \? \{ \[ \] \} \| \> \< | while read -d\  char;
    do
        [ "$i" = "$take" ] && echo "$char\c";
        ((i++));
    done
}

function rand_string {
    c=$1;
    while [ $c -gt 0 ];
        do char="${char}"$(rand_char);
        let c=$c-1;
    done
    echo $char
}

outputsalt=`rand_string $digits`

echo $outputsalt

      

if I enter 64 as the number of digits, the number of characters received will be different each try:

HeF6D>z}x[v=s(qRoPmNkLiIfG7E5C3A1yZwWtU§S~Q*O_M:J,b86|4]2{0)X&p    (63 chars)
WtUrSpQnOkLiJ,H8F6D4B1yZ)X&V$T!R+P_M:e;c9a7>5}2{u=s(q%o§m~j#hIfG   (64 chars)
_g:d,b86|4]w{u=r&p$n!lMjKhIeFcDaB>z0xYt)r&p§m~kLiJgHeFcDA1yZwX     (62 chars)
}w{u=s(q%oPmNkKhIfGdEbC3A1xYvWtUrS~Q*O_L.J,H8F6|4]2?Z)X&V$n!l+j_   (64 chars)
l+j_g:e;cDaB>z}x{u=sTqRoPmNkKhIfG7E5C3A1xYvW%U§S~Q*O_L.J,b86|4]    (63 chars)

      

Is there a way that the number of characters sticks to the specified number? Best wishes Ralph

+1


source to share


4 answers


Try a simpler case:

function rand_char {
  take=$(($RANDOM % 2)); i=0; echo a b | while read -d\  char;
  do
    [ "$i" = "$take" ] && echo "$char\c";
    ((i++));
  done
}

      

It will generate a

spaces as well, but not b

.

We can further reduce the problem to:

echo a b | while read -d\  char; do echo "$char"; done

      

which only writes a

, not b

. This is because you are instructing read

to read before a space and b

there is no space after , so it fails. This means that one out of every 88 characters will be flushed, which will result in your lines being slightly shorter.



The simplest solution is to add a dummy argument to create a space at the end:

echo {a..z} {A..Z} {0..9} (etc etc) \} \| \> \< '' | while read ...
#                                       Here ---^

      

Note that your method simply adds 15 bits of entropy to the salt, while the absolute minimum should be 64. It is much easier and safer to do this:

LC_CTYPE=C tr -cd 'a-zA-Z0-9,;.:_#*+~!@$%&()=?{[]}|><-' < /dev/urandom | head -c 64

      

(note: this replaces your unicode paragraph character with ascii @)

+5


source


No offense, according to your coding style, errr ... not the best I've seen :)

.



#!/bin/bash -e

read -p "Number of digits: " digits
# TODO: test that digits is really a number

chars=( {a..z} {A..Z} {0..9} \, \; \. \: \- \_ \# \* \+ \~ \! \§ \$ \% \& \( \) \= \? \{ \[ \] \} \| \> \< )

function rand_string {
    local c=$1 ret=
    while((c--)); do
        ret+=${chars[$((RANDOM%${#chars[@]}))]}
    done
    printf '%s\n' "$ret"
}

outputsalt=$(rand_string $digits)

echo "$outputsalt"

      

+4


source


I see two problems in your script.

I sure that

take=$(($RANDOM % 88));

      

it should be

take=$(($RANDOM % 87));

      

Otherwise, it looks like you are walking past the end of your input stream.

Another problem is char:

Bash sees this as two characters (wide char?). I will remove it from your options.

Of course, this would mean that the above line would be:

take=$(($RANDOM % 86));

      

Doing these two things essentially works for me.

Edited:

@, the other guy has a better answer. Adding space, not decreasing the modulus, ensures you get every character

+1


source


Another way to do it, if you fancy one-liners:

perl -le 'print map { ("a".."z","A".."Z",0..9,",",";",".",":","-","_","#","*","+","~","!","§","\$","%","&","(",")","=","?","{","}","[","]","|","<",">") [rand 87] } 1..63'

      

or, since you probably won't need a newline:

perl -e 'print map { ("a".."z","A".."Z",0..9,",",";",".",":","-","_","#","*","+","~","!","§","\$","%","&","(",")","=","?","{","}","[","]","|","<",">") [rand 87] } 1..63'

      

0


source







All Articles