나는 오늘의 단어(매일 무작위로)를 표시하는 bash 스크립트를 만들려고 합니다. 사전 파일이 있고 각 줄에는 단어와 그 정의가 있습니다.
date
나는 그것을 사용하여 매일의 독특한 가치를 얻고 싶습니다 . 이와 같이
today=$(date '+%Y%m%d') # will return 20160616 (for today)
이제 이 값을 사용하여 사전 파일에서 얻을 수 있는 줄 번호를 생성하고 싶습니다.
내 사전이 너무 86036
길어서 와 사이의 값으로 변환해야 합니다 $today
.1
86036
이를 수행하는 가장 좋은 방법은 무엇입니까?
답변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: 누구든지 내 원본 코드에서 문제를 발견할 수 있나요? 글쎄, $RANDOM
32767(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