나는 난수를 생성하는 프로그램을 만들고 있는데 난수를 생성하기 전에 얼마나 많은 조합이 있는지 표시하고 싶습니다. 이 작업을 수행하면 다음과 같은 결과를 얻습니다.
64k@conroe$ bash random A-Za-z0-9 3
238328
possible combinations
CG1
나는 "가능한 조합"이 "238328"과 같은 줄에 있기를 원합니다.
238328 possible combinations
해당 부분의 코드는 다음과 같습니다.
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"
이 시간을 단축할 수 있는 방법이 있다면 기꺼이 제안을 받고 싶습니다. 저는 bash 스크립팅을 처음 접했습니다.
echo | bc
또한 쉼표로 구분된 숫자를 출력 할 수 있는 방법이 있습니까 ? 일부 숫자는 매우 커질 수 있습니다. 즉, random A-Za-z0-9 10
가능한 조합의 수는 입니다 839299365868340224
. 표시할 수 있도록 쉼표로 구분하고 싶습니다 839,299,365,868,340,224
. 전체 코드:
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 '\033[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 '\033[0m'
}
done
exit 1
fi
답변1
다른 것이 없다면 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./'
}
글쎄요, 사과해야겠습니다. 제가 생각했던 char 클래스가 문자 그대로의 매개변수 문자열이라고 생각했는데, 여러분이 그것을 구문 분석하고 있다는 사실을 방금 깨달았습니다. 이제 나는 당신이 말하는 것을 이해합니다. 방금 작동하게 되었어요 - 실제로 작동해요하다차이를 계산하므로 모든 유형의 문자를 처리할 수 있습니다.
{ 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
}
산출
1 possibility.
2 possibilities.
3 possibilities.
4 possibilities.
9 possibilities.
19683 possibilities.
가장 먼저 해야 할 일은 printf
두 번째 매개변수를 시도하는 것입니다. ${2##*[!0-9]*}
숫자가 아닌 문자가 포함된 경우 매개변수 확장을 거쳐 null로 렌더링됩니다. %d
igit 값의 산술 확장이 선행되고 전체 실행 루프가 발생합니다. 이 산술 확장은 다음과 같습니다. 진행중. 실제로 전체 함수는 printf
현재 셸의 관점에서 본 설명일 뿐입니다.
그러나 $((
수학 확장 에서는 ))
이는 $(
명령 대체일 )
뿐이며 그 이상은 아닙니다. 우리는 어떤 숫자도 제공하지 않습니다. 단지 그것뿐입니다 $(($()))
.
명령 대체의 서브쉘을 제외하면 루프를 실행하고 출력을 수집합니다. 우리의 출력은 마침내 실행 가능한 산술 표현식으로 합쳐졌습니다.
$a
루프에서는 항상 각 루프의 맨 위에 첫 번째 문자를 넣습니다 $x
. 다음으로, $a
일부 패턴을 기반으로 현재 값의 헤더를 확인합니다 case
. 그 중 첫 번째는 다음과 같습니다.
([a-z]-["$x"-z]*|[A-Z]-["$x"-Z]*)
$a
여기서는 두 번 저장한 첫 번째 문자를 사용합니다 $x
. 첫째, 우리의 모델을 비교하는 논증입니다. 그러나 두 번째로 이는 $a
세 번째 문자에 대한 제한기입니다. 이는 세 번째 문자가 알파벳 범위 내에 들어갈 뿐만 아니라 $a
첫 번째 문자보다 크거나 같도록 보장합니다. 유효하지 않은 범위이기 때문에 z-a
테스트에 사용할 때 일치하지 않습니다.$x
이 패턴이 일치하면 헤더에서 두 문자를 제거한 후 각 합계의 ASCII 숫자 값을 인쇄합니다 $x
.$a
$a
이와 같이:
printf '(%d-%d+1)+' "'$x" "'$a"
...이것은 최종 산술에서 괄호 하위 표현식이 되며 범위 사이의 거리를 계산합니다.
숫자에도 동일한 작업을 수행합니다.
([0-9]-["$x"-9]*)
$a
이 경우에도 머리를 자릅니다. 숫자에 대한 수학은 약간 다릅니다. 음수를 얻습니다. $a
의 처음 세 문자는 에 저장 됩니다 $x
.x=4-9
그래서 우리는 다음을 인쇄합니다:
printf "$((-($x)+1))+"
담당자의 경우$a
것 같다처음 두 테스트에서 여전히 실패하는 범위와 마찬가지로 (?-*)
패턴과 일치하고 상위 두 문자를 제거 echo 2+
하고 다시 반복합니다.
패턴까지 설정하면 가능한 범위에서 첫 번째 항목이 일치할 때까지 (?*)
처음부터 $a
모든 것을 삭제합니다 $a
. 성공하면 계속해서 루프를 반복하고 차이를 분할하지만 나머지 부분에 대해 가능한 범위 일치가 없으면 기본적으로 여기에서 모든 권한과 에코를 $a
소비하므로 루프를 종료합니다 .$a
${#a}+
글쎄, 우리는 포기하지 않을 거야하지만$a
- 루프의 상단이 빈 상태로 다시 보내질 때까지 루프는 종료되지 않습니다 . 이런 일이 발생하면 ! echo 0
출력에 기록된 마지막 문자열을 실행합니다.
따라서 현재 셸로 돌아가서 수학 확장의 모든 내용을 print 로 평가하면 "$((subshell_math))^$2"
출력 bc
이 파이프로 연결되어 출력에 sed
문자열이 추가 됩니다.possibles.
이것이 작동하는 방식입니다.
답변2
백틱을 사용하여 출력을 저장한 다음 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
코드를 정리하는 측면에서 나중에 매개변수를 어떻게 사용하는지 모르면 조금 어렵지만, 한 가지 바꾸고 싶은 점은 가능한 모든 순열을 찾는 대신 예상되는 부분을 한 번에 확인하는 것입니다.
#!/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