2016-09-11 2 views
0

Ich habe ein einfaches Bash-Skript, das 4 Wörter zufällige Passphrasen aus einer Liste von Tausenden von Wörtern generiert. Jetzt bin ich mir nicht sicher, ob es wirklich sicher oder effizient für meinen persönlichen Gebrauch ist, lassen Sie mich wissen, wenn Sie über Verbesserungen nachdenken. Aber das ist nicht der Hauptpunkt. Check it out ->Warum die gleiche Funktion oft mit verschiedenen Argumenten aufrufen ist langsamer

Also, wenn ich es in meinem Laptop laufen, die Ein- und Ausgabe wie folgt aussieht:

time sh genpass 
astrology cringe tingling massager 

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

Ein zweites Mal: ​​

$ time sh genpass 
prankish askew siren fritter 

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

kann manchmal ganz lustig sein.

Wie auch immer, dies ist das Skript:

# 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}" 

sehen, wo ich für jede Art von Wort ein Array erstellen habe? 3 Arten, 3 Arrays. Nun, ich dachte darüber nach, diesen Code in einer Funktion zu bekommen, also müsste ich diese Funktion nur 4 Mal aufrufen, eine für jedes meiner 4 Wörter, mit einem anderen Argument. Ich dachte wirklich, es wäre schneller. Hier

ist die Codeänderung:

# 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) 

Jetzt ist hier die Eingabe/Ausgabe:

$ time sh genpass 
overstay clench napping palace 

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

Und wieder:

$ time sh genpass 
gainfully cameo extended nutshell 

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

Die Unterschiede im Timing sind nicht so groß von einem Deal, obwohl insgesamt dachte ich, es könnte definitiv schneller sein.

Also haben Sie eine Idee, warum das zweite Skript langsamer als das erste ist?

+0

Natürlich „, Astrologie "und" overstay "sind keine Adjektive. Deine Regeln müssen angepasst werden. – tripleee

+0

Ist nicht wirklich wichtig, die Zufälligkeit ist wichtig. Ich hätte diese "Verb - Adj - Substantiv" - Sache tatsächlich überspringen und das Skript nur 4 völlig zufällige Wörter ausgeben lassen können, aber ich dachte, es wäre süß. Entweder ich passe die Regeln an, entweder werde ich sie los. Wäre sicherlich schneller, sie loszuwerden. Aber nicht so süß ... –

+3

1. Wenn Sie so oft "awk" aufrufen müssen, dann schreiben Sie einfach das Ganze in "awk". 2. Wie auch immer, wenn Sie die gleiche Datei mehrmals analysieren, tun Sie sicherlich etwas falsch. 3. Sie dürfen nicht 'awk' verwenden, um ein zufälliges Element aus einem Array abzurufen. Das ist wirklich albern. Sie haben direkten Zugriff auf jedes Feld des Arrays. 4. Wenn Sie das Gefühl haben, dass Sie "Referenzen" brauchen (das ist, was Sie mit 'declare -a list_a = (" $ {! 1} ") tun), dann ist entweder Ihr Design falsch, oder Sie verwenden nur die falsche Sprache für den Job: Shell-Skripte sollten solche Funktionen nicht verwenden. –

Antwort

2

Sie haben mehr Code, der mehr Sachen macht, alles unnötig. Hier ist, wie zu tun, was Sie zu tun versuchen:

$ 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 

Die oben ausgeführt wurde gegen diese „Worte“ Datei aus dem Beispielausgabe erstellt Sie in Ihrer Frage zur Verfügung gestellt:

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

Das macht sicherlich den Job, Danke und so viel schneller, ich denke mal, wir müssen uns mehr mit awk beschäftigen. Kannst du erklären, was man mit 'srand()' meint, hier, bitte? Bedeutet das nur, dass du einen Samen erzeugst, bevor du diese 'grw nennst? ? 'Funktionen dreimal Ist es bedeutet, dass wir die gleichen Samen, die dreimal um verwenden –

+0

' Zeit awk -f genpass.awk ~/wordList.txt' -> stickig Opa unblessed skydiver echte \t 0m0.045s Benutzer \t 0m0.038s sys \t 0m0.005s –

+1

Es generiert a seed für den ersten Aufruf von rand() basierend auf der aktuellen Uhrzeit. Der 2. Aufruf von rand() benutzt als Ausgangswert die Ausgabe des ersten Aufrufs von rand() usw. Ohne srand() jedesmal wenn Sie awk den ersten aufrufen rand() würde mit dem gleichen Startwert beginnen und so würde jeder Aufruf von awk die gleiche Folge von "zufälligen" Zahlen erzeugen. Lesen Sie das Buch Effective Awk Programming, 4. Ausgabe, von Arnold Robbins, um awk zu lernen und sofort zu lernen, dass die Shell eine Umgebung ist, aus der Werkzeuge mit einer Sprache aufgerufen werden können, um diese Aufrufe zu sequenzieren, es ist KEIN Werkzeug zur Manipulation von Text, das ist was awk ist für. –

Verwandte Themen