날짜 명령을 변수에 전달하시겠습니까?

날짜 명령을 변수에 전달하시겠습니까?

좋아, 내 질문은 다음과 같습니다. 이 질문을 통과하고 싶습니다.

echo $(($(date +%s%N)/1000000))

이는 다음과 같이 변수 "a"에 추가될 수 있습니다.

a=$(($(date +%s%N)/1000000))

이렇게 하는 이유는 4개의 난수(Random Number)를 사용하고 싶기 때문입니다. 예제를 보여주기 위해 이 bash 스크립트를 만들었습니다.

#!/bin/bash
for (( c=0; c<=10; c++))
do
        echo $(($(date +%s%N)/1000000))
        sleep .5
done

출력: - (처음 9자리 무시)

1622001937610
1622001938249
1622001938758
1622001939267
1622001939774
1622001940282
1622001940790
1622001941299
1622001941807
1622001942315
1622001942823

이제 인스턴스 중 하나의 결과를 마지막 9자리부터 인덱싱된 배열에 추가하여 나노초 시간을 기준으로 4개의 난수를 수신하려고 합니다.

그러나 결과를 얻기 위해 bash에서 사용되는 구문을 완전히 이해하지 못하는 것 같습니다. date +%s%N)/1000000배열을 직접 호출 할 수 있나요 ? 내 생각은 배열을 만들고 비운 다음 결과를 배열에 추가하고 9번째 숫자부터 인덱싱을 시작하는 것이기 때문입니다. 그 결과를 내가 처리할 수 있는 두 번째 변수에 전달합니다.

결과를 date +%s%N)/1000000변수로 변환하는 방법을 배우는 것만으로도 많은 도움이 될 것입니다.

고통을 끼쳐드려 죄송합니다. 미리 감사드립니다.

답변1

나의 초기 접근 방식은 출력에서 ​​문자열 조작을 사용하여 date원하는 값을 얻는 것이었습니다. 여기 버전은 수학(1000000 모듈로 10000으로 나누기)을 사용하지만 댓글에 대안을 남겼습니다.

#!/bin/bash
items=()

random=$(( ($(date +%s%N) / 1000000) % 10000 ))        # Second and milliseconds
# random=$( date +%s%N | grep -oP '....(?=......$)' )

items+=($random)                                       # Append value to array

echo "${items[0]}"                                     # First array value
echo "${items[-1]}"                                    # Last (most recently appended) value
declare -p items                                       # Visual inspection of array elements

답변2

당신은 그것을 사용할 수 있습니다${var:offset:length} 매개변수 확장 구문값의 하위 문자열을 추출합니다.

$ nanoseconds=$(date +%N)
$ printf '%s\n' "$nanoseconds" "${nanoseconds:2:4}"
785455000
5455

또는 권장되는 대로 /dev/urandom을 사용하십시오.

$ tr -dc '[:digit:]' < /dev/urandom | fold -w 4 | head -n 10
8386
9194
3897
8790
4738
1453
4323
9021
6033
8889

bash 명령을 사용하여 배열로 읽어옵니다 mapfile.

$ mapfile -t numArray < <(tr -dc '[:digit:]' < /dev/urandom | fold -w 4 | head -n 10)
$ declare -p numArray
declare -a numArray=([0]="2851" [1]="9684" [2]="5823" [3]="5206" [4]="3208" [5]="2914" [6]="0395" [7]="4128" [8]="1876" [9]="5691")

답변3

run 하면 date +%s%N출력은 다음과 같습니다.

1622046533072036066
ssssssssssmmmuuunnn

오른쪽의 숫자는 더 작은 단위를 나타냅니다. ( m// 밀리/마이크로/나노초를 u나타냅니다 .)n

이렇게 1000000으로 나누면 $(( ... / 1000000))맨 오른쪽 6자리를 없애고 초와 밀리초만 남게 됩니다.

이것은 매우 무작위가 아닙니다. 예를 들어, 테스트 실행에서 연속 출력 숫자는 다소 일관된 508만큼 증가합니다. 이는 밀리초 단위로 요구 사항인 0.5초와 거의 일치합니다.

다음으로 변경하면 더 많은 임의의 값을 얻을 수 있습니다.예약하다가장 오른쪽 숫자와 선행 숫자는 모듈로 연산자를 사용하여 제거됩니다 $(( ... % 1000000)). 하지만 시스템에 충분히 세분화된 시계가 없으면 가장 낮은 숫자가 무작위가 아닐 수도 있습니다.

date낮은 숫자만 유지한다면 실제로 전체 초 수를 출력할 필요는 없지만 그냥 사용하면 됩니다 +%N. 단, 나노초 값은 항상 0부터 9자리까지 채워지고 Bash는 0으로 시작하는 숫자를 다음과 같이 처리합니다. 8진수이므로 092345678오류가 발생합니다. 앞에 추가 숫자를 추가하면 이를 방지할 수 있지만 초 값을 추가하면 이를 방지할 수도 있습니다.

내 시스템에서는 다음 루프의 연속 반복에 대한 값의 차이가 대략 1470000~1560000ns(약 1.5ms/반복) 범위이므로 가장 오른쪽 숫자 4개 이상은 사용하지 않을 것입니다.

#/bin/bash
array=()
prev=$(date +%s%N)
for ((i=0; i < 100; i++)); do 
        this=$(date +%s%N)
        # diff=$(( (this - prev) % 1000000000))
        diff=$(( (this - prev) % 10000))
        printf "$prev $this %04d\n" "$diff"
        array+=("$diff")
        prev=$this
done

산술 연산을 수행하는 대신 출력을 date문자열로 처리하고 일부 문자를 자를 수 있습니다. 마지막 4자가 남습니다.

a=$(date +%N)
a=${a: -4}

shuf그런 다음 다시 섞는 것에 국한되지 않고 반복을 통해 값을 선택할 수도 있는 GNU coreutils와 같은 난수를 생성하는 다른 방법을 고려할 수 있습니다 . 예를 들어, 다음은 각각 4자리 숫자로 구성된 20개의 숫자를 인쇄합니다.

shuf -i 0000-9999 -r -n 20

또는 몇 가지 후프를 사용하여 제로 패딩을 얻습니다.

shuf -i 10000-19999 -r -n 20 |sed -e 's/^1//'

다음을 사용하여 출력을 배열로 읽을 수 있습니다 readarray.

readarray array < <(shuf -i 0000-9999 -r -n 20)

당연히 shuf셸에서 반복하는 것보다 훨씬 빠릅니다 date. -i 0-9단위 수를 가져오는 등 더 작은 범위를 사용할 수도 있습니다 .

관련 정보