Como fazer isso 'echo | bc 'saída estar na mesma linha que a saída de eco depois?

2

Estou fazendo um programa para gerar números aleatórios e, antes que ele seja gerado, quero mostrar quantas combinações existem. Quando eu faço isso, eu entendo isso:

64k@conroe$ bash random A-Za-z0-9 3
238328
possible combinations
CG1

Eu quero que 'combinações possíveis' estejam na mesma linha que '238328', então eu obtenho

238328 possible combinations

Este é o código da seção:

if [ $1 == 'A-Z' ] || [ $1 ==  'a-z' ]
then
    echo "26^$2" | bc 
elif [ $1 == 'A-Za-z' ] || [ $1 ==  'a-zA-Z' ]
then
    echo "52^$2" | bc
elif [ $1 == 'A-Z0-9' ] || [ $1 ==  'a-z0-9' ]
then
    echo "36^$2" | bc
elif [ $1 == 'A-Za-z0-9' ] ||[ $1 == 'a-zA-Z0-9' ]
then
    echo "62^$2" | bc
else
    echo "${#$1}^$2" | bc 

fi
echo "possible combinations"

Se houver alguma maneira de tornar isso mais curto também, eu adoraria receber sugestões. Eu ainda sou relativamente novo no bash scripting.

Além disso, existe alguma maneira possível de obter o echo | bc para gerar um número separado por vírgulas? Alguns números podem ficar muito grandes, por exemplo, para random A-Za-z0-9 10 , o número de combinações possíveis é 839299365868340224 . Eu quero que seja separado por vírgula, então ele mostra 839,299,365,868,340,224 . Código completo:

if [ $1 == 'A-Z' ] || [ $1 ==  'a-z' ]
then
    echo "26^$2" | bc 
elif [ $1 == 'A-Za-z' ] || [ $1 ==  'a-zA-Z' ]
then
    echo "52^$2" | bc
elif [ $1 == 'A-Z0-9' ] || [ $1 ==  'a-z0-9' ]
then
    echo "36^$2" | bc
elif [ $1 == 'A-Za-z0-9' ] ||[ $1 == 'a-zA-Z0-9' ]
then
    echo "62^$2" | bc
else
    echo "${#$1}^$2" | bc 

fi
echo "possible combinations"
if [ $# == 2 ]
then
    < /dev/urandom env LC_CTYPE=C tr -dc $1 | head -c $2 | while read -n 1 x 
    do
    printf "\e[1;36m$x"
    sleep 0.03
    done
    echo -e '3[0m'
    exit 0
exit 1
elif [ $# == 3 ]
then

for (( c=1; c<=$3; c++ ))
 do {
        < /dev/urandom env LC_CTYPE=C tr -dc $1 | head -c $2 | while read -n 1 x 
    do
    printf "\e[0;33m$x"
    sleep 0.03
    done
    echo -e '3[0m'
}
done


exit 1
fi
    
por 智障的人 17.06.2015 / 22:20

2 respostas

2

Se nada mais, você precisa de uma declaração case .

random(){
        printf "%d^${2##*[!0-9]*}\n"  "$(($(
                export  LC_ALL=C; a=$1
                while   x=${a%"${a#?}"} s=
                        case  $a     in
                        ([a-z]-["$x"-z]*|[A-Z]-["$x"-Z]*)
                                a=${a#??} s=?
                                printf  '(%d-%d+1)+' "'$a" "'$x";;
                        ([0-9]-["$x"-9]*)
                                x=${a%"${a#???}"} a=${a#"$x"}
                                printf  "$((-($x)+1))+";;
                        (?-*)   a=${a#??}
                                echo 2+;;
                        (?*)    x=${a%%[A-Za-z0-9]-*}
                                a=${a#"$x"}
                                echo "${#x}+";;
                        (*) !   echo 0          ;;esac
                do              a=${a#$s}       ; done
        )))"    |       bc|     sed 's/$/ possibilities./
                                      /^1 /s/....$/y./'
}

Ok, eu tenho que me desculpar - eu só agora percebi que o que eu achava que eram classes de caracteres eram sequências de caracteres literais - e que você estava analisando-as. Agora eu entendo o que você é. Eu fiz isso funcionar agora - ele realmente faz os intervalos, e você pode lidar com qualquer tipo de personagem - porque isso conta a diferença.

{   random A 1       #1  char        and 1
    random AB 1      #2  chars       and 1
    random a-Z 1     #3  chars because the range is invalid and 1
    random aa-c 1    #4  chars: aabc and 1
    random a-c 2     #3  chars: abc  and 2
    random aa-z 3)   #27 chars:aa-z  and 3
}

OUTPUT

1 possibility.
2 possibilities.
3 possibilities.
4 possibilities.
9 possibilities.
19683 possibilities.

A primeira coisa que é feita é tentar printf nosso segundo argumento - que sofre% de expansão do parâmetro${2##*[!0-9]*} para torná-lo nulo se contiver qualquer caractere não numérico - precedido pelo valor %d igit de um expansão aritmética em que todo o nosso ciclo de execução ocorre. De fato, a função inteira é uma instrução printf da perspectiva do shell atual.

Mas na expansão $(( math )) é uma substituição do comando $( ) - e isso é tudo. Nós fornecemos sem números - é apenas $(($())) .

Exceto que a subshell dentro da substituição de comando executa nosso loop e coleta nossa saída. Nossa saída eventualmente resulta em uma expressão aritmética viável.

Dentro do loop sempre colocamos o primeiro caractere de $a em $x no topo de cada um. Em seguida, verificamos a cabeça do nosso valor atual para $a em relação a alguns padrões case . A primeira delas é assim:

([a-z]-["$x"-z]*|[A-Z]-["$x"-Z]*)

Aqui, usamos o primeiro caractere de $a - que salvamos em $x - duas vezes. Em primeiro lugar, é o argumento contra o qual comparamos nosso padrão. Mas, em segundo lugar, é um limitador para o terceiro caractere de $a - garante que o terceiro caractere não apenas se encaixe em uma faixa alfabética, mas também que seja maior ou igual a primeiro caractere de $a personagem. Porque z-a é um intervalo inválido e não corresponde quando usamos $x para testar.

Se correspondermos a esse padrão, imprimiremos o valor do dígito ascii de cada $x e $a depois de removermos da cabeça $a dois caracteres.

Assim:

printf '(%d-%d+1)+' "'$x" "'$a"

... que se torna uma subexpressão parantética na nossa aritmética final e avalia a distância entre o nosso alcance.

Fazemos o mesmo para os dígitos:

 ([0-9]-["$x"-9]*)

E também tiramos a cabeça de $a nesse caso. A matemática para os dígitos é um pouco diferente - temos o negativo. Os primeiros três caracteres de $a são salvos em $x , como x=4-9 .

E assim imprimimos:

printf "$((-($x)+1))+"

No caso de o cabeçalho de $a parecer como um intervalo, mas ainda assim falhar nos dois testes anteriores e corresponder ao nosso padrão (?-*) , então removeremos o topo dois caracteres, echo 2+ e ciclo novamente.

Se chegarmos ao ponto tão baixo quanto o padrão (?*) , então removeremos a faixa de $a de tudo até a primeira correspondência de intervalo possível em $a . Se tivermos sucesso, continuaremos a fazer o loop e apenas dividiremos a diferença, mas se não houver correspondência possível no intervalo no restante de $a , sairemos do loop porque consumiremos todo o $a right aqui e echo ${#a}+ , basicamente.

Bem, não vamos sair ainda - o loop nunca sai até que $a seja enviado de volta ao topo do loop vazio. Quando isso acontece, fazemos ! echo 0 , que é a última string que escrevemos para a saída.

Então, volte ao shell atual e avalie tudo na expansão matemática para imprimir "$((subshell_math))^$2" at bc cuja saída é canalizada para sed , que acrescenta a string possibles. à sua saída.

E é assim que funciona.

    
por 17.06.2015 / 23:25
0

Eu salvaria a saída usando backticks, então você pode formatá-la com printf:

if [ $1 == 'A-Z' ] || [ $1 ==  'a-z' ]
then
    combinations='echo "26^$2" | bc'
elif [ $1 == 'A-Za-z' ] || [ $1 ==  'a-zA-Z' ]
    combinations='echo "52^$2" | bc'
# ... and so on ...
fi

printf "%'.0f possible combinations\n" $combinations

No que diz respeito a limpar seu código, é um pouco mais difícil sem saber como você está usando os parâmetros mais tarde, mas uma coisa que eu mudaria é verificar as partes que você espera uma por vez, em vez de procurar todas as permutações possíveis.

#!/bin/bash

chars='0'
if  [[ $1 == *"0-9"* ]]; then
    chars="$chars+10"
fi
if  [[ $1 == *"a-z"* ]]; then
    chars="$chars+26"
fi
if  [[ $1 == *"A-Z"* ]]; then
    chars="$chars+26"
fi

combinations='echo "($chars)^$2" | bc'
printf "%'.0f possible combinations\n" $combinations
    
por 17.06.2015 / 22:37