2016-09-11 9 views
0

수천 개의 단어 목록에서 4 단어 임의 암호문을 생성하는 간단한 bash 스크립트를 작성했습니다. 이제는 내 개인적인 용도로 정말 안전하고 효율적인지 확실하지 않습니다. 여러분은 개선 사항에 대해 생각한다면 알려 주시기 바랍니다. 하지만 그게 주요 포인트가 아닙니다. 그것을 체크 아웃 - 나는 내 노트북에서 실행하면다른 인수로 여러 번 동일한 함수를 호출하는 것이 왜 느린가

그래서, 입력 및 출력은 다음과 같습니다> :

time sh genpass 
astrology cringe tingling massager 

real 0m0.319s 
user 0m0.267s 
sys  0m0.077s 

두 번째 시간 :

$ time sh genpass 
prankish askew siren fritter 

real 0m0.318s 
user 0m0.266s 
sys  0m0.077s 

때로는 매우 재미있을 수 있습니다.

# EDITABLES ########################################### 
target="/path/to/my/wordList.txt" 
# END EDITABLES ####################################### 

getWordList() { 
    case $1 in 
    "verb") mawk '/ing$|ed$|en$/ {print $2}' $target ;; 
    "adjective") mawk '/y$|ish$/ {print $2}' $target ;; 
    "noun") mawk '!/ing$|ed$|en$|y$|ish$/ {print $2}' $target ;; 
    *) printf "%s" "'${1}' is an invalid argument." && echo && exit 1 
    esac 
} 

pickRandomLineNumber() { 
    # Get the list in an array 
    declare -a list_a=("${!1}") 
    # How many items in the list 
    local length="${#list_a[@]}" 
    # Generate a random number between 1 and the number of items in the list 
    local number=$RANDOM 
    let "number %= $length" 
    # Print the word at random line 
    printf "%s\n" ${list_a[@]} | mawk -v line=$number 'NR==line {print}' 
} 

read -ra verbList <<< $(getWordList verb) 
verb=$(pickRandomLineNumber verbList[@]) 

read -ra adjectiveList <<< $(getWordList adjective) 
adjective=$(pickRandomLineNumber adjectiveList[@]) 

read -ra nounList <<< $(getWordList noun) 
noun1=$(pickRandomLineNumber nounList[@]) 
noun2=$(pickRandomLineNumber nounList[@]) 

printf "%s %s %s %s\n" "${adjective}" "${noun1}" "${verb}" "${noun2}" 

나는 단어의 각 유형의 배열을 만들 필요가 어디를 참조하십시오 :

어쨌든,이 스크립트입니까? 3 가지 유형, 3 가지 배열. 글쎄, 함수에서 코드를 가져 오는 것에 대해 생각해 봤는데, 나는 그 함수를 4 번 (각각 4 단어마다 하나씩 다른 인수로) 호출해야했습니다. 나는 그것이 더 빠를 것이라고 정말로 생각했다. 현재 이곳에

# EDITABLES ########################################### 
target="/path/to/my/wordList.txt" 
# END EDITABLES ####################################### 

getWordList() { 
    case $1 in 
    "verb") mawk '/ing$|ed$|en$/ {print $2}' $target ;; 
    "adjective") mawk '/y$|ish$/ {print $2}' $target ;; 
    "noun") mawk '!/ing$|ed$|en$|y$|ish$/ {print $2}' $target ;; 
    *) printf "%s" "'${1}' is an invalid argument." && echo && exit 1 
    esac 
} 

pickRandomLineNumber() { 
    # Get the list in an array 
    declare -a list_a=("${!1}") 
    # How many items in the list 
    local length="${#list_a[@]}" 
    # Generate a random number between 1 and the number of items in the list 
    local number=$RANDOM 
    let "number %= $length" 
    # Print the word at random line 
    printf "%s\n" ${list_a[@]} | mawk -v line=$number 'NR==line {print}' 
} 

#### CHANGE #### 
getWord() { 
    read -ra list <<< $(getWordList $1) 
    local word=$(pickRandomLineNumber list[@]) 
    printf "%s" "${word}" 
} 

printf "%s %s %s %s\n" $(getWord adjective) $(getWord noun) $(getWord verb) $(getWord noun) 

입력/출력 : 여기에

코드의 변화를 다시

$ time sh genpass 
overstay clench napping palace 

real 0m0.403s 
user 0m0.304s 
sys  0m0.090s 

그리고 : 타이밍

$ time sh genpass 
gainfully cameo extended nutshell 

real 0m0.369s 
user 0m0.304s 
sys  0m0.090s 

의 차이가 큰되지 않습니다 전반적으로, 나는 그것이 더 빠를 수 있다고 생각했다.

왜 두 번째 스크립트가 첫 번째 스크립트보다 느린 지 알 수 있습니까?

+0

, "점성술을 여기에 당신이하려고하는 일을하는 방법 "과"overstay "는 형용사가 아닙니다. 규칙에 약간의 조정이 필요합니다. – tripleee

+0

정말로 중요하지 않습니다. 임의성이 중요합니다. 실제로 그 "동사 - 동사 - 명사"를 건너 뛰고 스크립트에서 완전히 임의의 단어 4 개를 출력 할 수는 있었지만 나는 그것이 달콤 할 것이라고 생각했습니다. 규칙을 조정하거나 둘 중 하나를 제거합니다. 확실히 빨리 제거하는 것이 더 빠를 것입니다. 하지만 달콤한 것은 아닙니다 ... –

+3

1. awk를 여러 번 호출해야한다면, 모든 것을 awk로 스크립트하십시오. 2. 어쨌든 동일한 파일을 여러 번 구문 분석하는 경우 분명히 잘못된 작업을 수행하고있는 것입니다. 3. 배열에서 무작위 요소를 검색하는 데 awk을 사용하지 마십시오. 정말 어리 석다. 어레이의 모든 필드에 직접 액세스 할 수 있습니다. 4. "references-a list_a = ("$ {! 1} ")')를 사용하여"참조 "가 필요하다고 느끼면 디자인이 잘못되었거나 방금 작업 언어가 잘못되었습니다. 셸 스크립트는 이러한 기능을 사용하지 않아야합니다. –

답변

2

더 많은 작업을 수행하는 코드가 더 필요합니다.

$ cat tst.awk 
function grw(arr) {  # Get Random Word 
    return arr[int(rand() * length(arr)) + 1] 
} 

{ 
    if (/(ing|ed|en)$/) verbs[++numVerbs] = $0 
    else if (/(y|ish)$/) adjectives[++numAdjectives] = $0 
    else nouns[++numNouns] = $0 
} 

END { 
    srand() 
    printf "%s %s %s %s\n", grw(adjectives), grw(nouns), grw(verbs), grw(nouns) 
} 

$ awk -f tst.awk words 
overstay clench siren clench 
$ awk -f tst.awk words 
prankish nutshell tingling cameo 
$ awk -f tst.awk words 
astrology clench tingling palace 

위의 당신이 당신의 질문에 제공되는 샘플 출력에서 ​​생성이 "단어"파일에 대해 실행되었습니다 : 물론

$ cat words 
askew 
astrology 
cameo 
clench 
cringe 
extended 
fritter 
gainfully 
massager 
napping 
nutshell 
overstay 
palace 
prankish 
siren 
tingling 
+1

확실히 그 일을합니다. 고마워 그리고 훨씬 더 빨리 awk에 대해 더 많은 것을 알아야 할 필요가있다. 'srand()'의 사용법을 설명 할 수 있겠는가? 여기'grw'를 호출하기 전에 시드를 생성한다는 것을 의미 하는가? ?'세 번 기능은 우리가 주위에 같은 씨에게 세 번 사용하는 것을 의미합니까 –

+0

'시간 AWK -f genpass.awk ~/wordList.txt' -> 답답한 할아버지 저주받은 스카이 다이버 실제 \t 0m0.045s 사용자 \t 0m0.038s sys \t 0m0.005s –

+1

rand()에 대한 두 번째 호출은 rand() 등의 첫 번째 호출 결과를 시드로 사용합니다. awk를 호출 할 때마다 srand()가 없으면 첫 번째 호출에서 rand rand()는 동일한 시드 값으로 시작하므로 awk를 호출 할 때마다 "임의"숫자의 동일한 순서가 생성됩니다. Arnold Robbins의 Effective Awk Programming, 4th Edition을 읽고 awk를 배우고 그 쉘이 언어를 가진 도구를 호출하여 문자를 처리 할 수있는 환경임을 즉시 배우고, 텍스트를 조작하는 도구가 아니라 awk 에 대한 것입니다. –