이 `echo | bc` 출력과 후속 echo 출력을 같은 줄에 만드는 방법은 무엇입니까?

이 `echo | bc` 출력과 후속 echo 출력을 같은 줄에 만드는 방법은 무엇입니까?

나는 난수를 생성하는 프로그램을 만들고 있는데 난수를 생성하기 전에 얼마나 많은 조합이 있는지 표시하고 싶습니다. 이 작업을 수행하면 다음과 같은 결과를 얻습니다.

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로 렌더링됩니다. %digit 값의 산술 확장이 선행되고 전체 실행 루프가 발생합니다. 이 산술 확장은 다음과 같습니다. 진행중. 실제로 전체 함수는 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

관련 정보