2016-09-11 3 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つの単語ごとに1つずつ、別の引数で呼び出す必要があります。私は本当に速いと思った。ここで

は、コード変更である:今ここに

# 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 

タイミングの違いはそれほど大きくありません全体的には間違いなくもっと速いと思った。

なぜ、2番目のスクリプトが最初のスクリプトより遅いのですか?

+0

、「占星術"と" overstay "は形容詞ではありません。あなたのルールには微調整が必​​要です。 – tripleee

+0

本当に問題ではありませんが、ランダム性が重要です。私は実際にそれらの "動詞 - 名詞"のことをスキップして、スクリプトに4つの全くランダムな単語を出力させることができましたが、私はそれが甘いと思っていました。ルールを調整するか、取り除くかのどちらかです。確かに速くそれらを取り除くだろうか。しかし、甘いものではありません... –

+3

1. awkを何度も呼び出す必要がある場合は、awkでスクリプト全体をスクリプト化してください。 2.とにかく、同じファイルを何度も解析しているなら、間違ったことをしていることは間違いありません。 3.配列からランダムな要素を取得するために 'awk'を使用しないでください。それは本当に愚かです。配列の任意のフィールドに直接アクセスできます。 4.「参照」が必要だと思うなら( 'declare -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

)あなたは 'srand()'の使い方を説明できますか?ここでは、 '' grw''を呼び出す直前にシードを生成することを意味しますか? ?? '3回の機能が、それは私たちが周りに同じシードを3回使用することを意味してい –

+0

'時間のawk -f genpass.awk〜/ wordList.txt' - > ムッおじいちゃんblessされていないスカイダイバー 本当\t 0m0.045s ユーザー\t 0m0.038s sys \t 0m0.005s –

+1

rand()への2回目の呼び出しは、rand()などへの最初の呼び出しの出力をシードとして使用します。awkを呼び出すたびにsrand()がなければ、 rand()は同じシード値で始まるので、awkを呼び出すたびに同じシーケンスの「ランダム」番号が生成されます。 Arnold RobbinsのEffective Awk Programming、第4版を読んで、awkを学び、シェルがそれらの呼び出しをシーケンスするための言語を持つツールを呼び出す環境であることを直ちに学びます。それはテキストを操作するツールではなく、awk 〜のためです。 –

関連する問題