날짜 시드 값 범위 내에서 행 번호/"인덱스" 생성

날짜 시드 값 범위 내에서 행 번호/"인덱스" 생성

나는 오늘의 단어(매일 무작위로)를 표시하는 bash 스크립트를 만들려고 합니다. 사전 파일이 있고 각 줄에는 단어와 그 정의가 있습니다.

date나는 그것을 사용하여 매일의 독특한 가치를 얻고 싶습니다 . 이와 같이

today=$(date '+%Y%m%d') # will return 20160616 (for today)

이제 이 값을 사용하여 사전 파일에서 얻을 수 있는 줄 번호를 생성하고 싶습니다.

내 사전이 너무 86036길어서 와 사이의 값으로 변환해야 합니다 $today.186036

이를 수행하는 가장 좋은 방법은 무엇입니까?

답변1

약간 다른 해결책: cron 작업을 사용하여 매일 텍스트 파일의 줄을 섞습니다. 그런 다음 스크립트는 첫 번째 행을 선택합니다.

Cron 작업( sort무작위로 데이터를 "정렬"할 수 있는 작업 필요 -R):

0 0 * * * sort -R -o wotd_data.txt wotd_data.txt

또는 cron이해 하신다면 @daily(참조 man 5 crontab):

@daily sort -R -o wotd_data.txt wotd_data.txt

스크립트:

head -n 1 wotd_data.txt

wotd_data.txt분명히 전체 경로가 필요합니다.

답변2

모듈로 수학!

$ today=`date +%Y%m%d`
$ echo $(( today % 86036 + 1 ))
28193

wc -l that file...파일 길이가 변경되면 86036이 발생할 수 있습니다...

답변3

쉘의 변수를 사용하여 RANDOM난수를 얻으십시오. 하지만 먼저 난수 생성기에 오늘 날짜를 입력하십시오(스크립트가 자정 이후로 사용되지 않은 경우). 그런 다음 파일에서 해당 행을 선택하십시오.

즉 (아래 Bash) ...

wotd_data="wotd_data.txt"

stamp="$HOME/.wotd-stamp"
stamp_random="$HOME/.wotd-random"

date_now=$( date +"%Y%m%d" )

if [ -f "$stamp" ]; then
    date_last=$( <"$stamp" )
else
    date_last=0
fi

if [ "$date_last" != "$date_now" ]; then
    RANDOM="$date_now"
    echo "$date_now" >"$stamp"
else
    RANDOM=$( <"$stamp_random" )
fi

number=$RANDOM
echo $number >"$stamp_random"

number=$RANDOM$RANDOM  # See the "Edit #2" note below

data_length=$( wc -l <"$wotd_data" )

line=$(( 1 + ( number % data_length ) ))

sed -n "${line}p" "$wotd_data"

이는 사용자의 타임스탬프 파일을 사용하여 $HOME마지막으로 명령을 실행한 시간을 추적합니다. 오늘이 아니면 $RANDOM오늘 날짜를 사용하여 다시 시드하고 오늘 날짜를 파일에 씁니다.

$RANDOM편집 #1: 현재 셸에 로컬이므로 마지막으로 사용한 nonce도 저장해야 했습니다 . 그렇지 않으면 다음 스크립트 호출 시 시드가 계속되지 않습니다. 나는 이것을 별도의 "임의 태그" 파일에 저장합니다. 파일을 사용하여 마지막 통화 날짜와 마지막으로 사용된 임의 번호를 기록하도록 이를 변경할 수 있습니다.

편집 #2: 누구든지 내 원본 코드에서 문제를 발견할 수 있나요? 글쎄, $RANDOM32767(16비트)을 넘지 않아야 하며 파일에는 그보다 더 많은 줄이 있다고 합니다. 이는 $RANDOM단독으로 사용하는 것이 좋지 않다는 것을 의미합니다. 그렇기 때문에 단순히 $RANDOM그 자체로 연결하여 더 긴 난수를 생성합니다. 시드 및 "무작위로 표시된" 파일은 이에 영향을 받지 않습니다.

편집 #3: OP가 "특정 날짜에 스크립트를 실행할 때마다 동일한 줄을 사용하세요"라고 요청했다는 사실을 방금 알아차렸습니다(어젯밤 늦게 내 두뇌가 이해하지 못한 댓글에서). 이것이 바로 내 스크립트가 수행하는 작업입니다.아니요그렇습니다 (동일한 결과를 제공합니다행 순서매일). 어쨌든, $RANDOM스크립트 호출 사이에 상태를 유지하는 유사한 문제가 있는 다른 사람에게 도움이 될 수 있도록 여기에 내 솔루션을 남길 것입니다 .

답변4

파일을 순차적으로 검토하는 것이 허용되지 않는 경우 다음과 같이 제안합니다. 파일의 모든 줄을 처리하는 데 230년 이상이 걸릴 것이며, 미래에 아직 결정되지 않은 지점에서 단어가 연속해서 반복될 것입니다. 런타임에 "단어" 파일의 줄 수(단어 정의)를 계산하여 더 유연하게 만들었습니다. 따라서 파일에서 줄을 추가하거나 제거하면 스크립트가 그에 따라 조정됩니다.

#!/usr/bin/env bash

# number of days since 1970-01-01 00:00:00
seed=$(( ($(date +%s) / 86400) ))
# initialize RNG to this seed
RANDOM=$seed
nwords=$(wc -l < words)
# generate two random numbers (0 .. 32767), multiply them,
# modulo nwords, plus 1 -> range 1..86036
r=$(( ((RANDOM * RANDOM) % nwords) + 1 ))
# print that line from the 'words' file
sed -n "${r}p" words

관련 정보