날짜 명령을 변수에 전달합니까?

날짜 명령을 변수에 전달합니까?

좋아, 내 문제는 다음과 같습니다. 이것을 통과하고 싶습니다.

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

변수 "a"에 다음과 같이 배열에 추가할 수 있습니다.

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

내가 이 일을 하는 이유는 4개의 임의의 숫자(임의의 숫자)를 가지고 놀고 싶기 때문입니다. 예제를 보여주기 위해 이 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

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

1622046533072036066
ssssssssssmmmuuunnn

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

마찬가지로 이를 1000000으로 나누면 $(( ... / 1000000))가장 오른쪽의 6자리 숫자가 제거되고 초와 밀리초만 남습니다.

그것들은 그다지 무작위적이지 않습니다. 예를 들어 테스트 실행에서 연속 출력 숫자는 다소 일관된 508만큼 증가합니다. 이는 밀리초 단위로 요청한 0.5초와 거의 일치합니다.

대신에 더 많은 임의의 값을 얻을 수 있습니다.유지된예를 들어 모듈로 연산자를 사용하여 가장 오른쪽 숫자를 삭제하고 앞의 숫자를 삭제했습니다 $(( ... % 1000000)). 시스템에 충분히 세밀하게 세분화된 시계가 없으면 가장 낮은 숫자도 무작위가 아닐 수도 있습니다.

date낮은 숫자만 유지하는 경우 실제로 전체 초를 출력 할 필요는 없지만 대신 just를 사용할 수 있습니다 +%N. 단, 나노초 값은 항상 9자리까지 0으로 채워지고 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}

그런 다음 난수를 생성하는 다른 방법을 고려할 수도 있습니다. 예를 들어 shufGNU 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한 자리 숫자를 얻으려면 더 작은 범위를 사용할 수도 있습니다 .

관련 정보