wake-up-neo.com

Was ist eine einfache Möglichkeit, eine zufällige Zeile aus einer Datei in der Unix-Befehlszeile zu lesen?

Was ist eine einfache Möglichkeit, eine zufällige Zeile aus einer Datei in der Unix-Befehlszeile zu lesen?

231
Newbie Prog

Sie können shuf verwenden:

shuf -n 1 $FILE

Es gibt auch ein Dienstprogramm namens rl. In Debian ist es im randomize-lines-Paket, das genau das tut, was Sie möchten, obwohl es nicht in allen Distros verfügbar ist. Auf seiner Homepage wird jedoch stattdessen die Verwendung von shuf empfohlen (die bei ihrer Erstellung nicht vorhanden war, glaube ich). shuf ist Teil der GNU coreutils, rl nicht.

rl -c 1 $FILE
343
unbeknown

Eine andere Alternative:

head -$((${RANDOM} % `wc -l < file` + 1)) file | tail -1
71
PolyThinker
sort --random-sort $FILE | head -n 1

(Ich mag den Shuf-Ansatz oben sogar noch besser - ich wusste gar nicht, dass es ihn gab und ich hätte dieses Werkzeug nie alleine gefunden)

Das ist ganz einfach. 

cat file.txt | shuf -n 1

Zugegeben, dies ist nur ein bisschen langsamer als die "shuf -n 1 file.txt".

25
Yokai

perlfaq5: Wie wähle ich eine zufällige Zeile aus einer Datei aus? Hier ist ein Reservoir-Sampling-Algorithmus aus dem Kamelbuch:

$ Perl -e 'srand; Rand($.) < 1 && ($line = $_) while <>; print $line;' file

Dies hat einen erheblichen Platzvorteil gegenüber dem Lesen der gesamten Datei. Einen Beweis für diese Methode finden Sie in Die Kunst der Computerprogrammierung, Band 2, Abschnitt 3.4.2 von Donald E. Knuth.

14
Tracker1

mit einem Bash-Skript:

#!/bin/bash
# replace with file to read
FILE=tmp.txt
# count number of lines
NUM=$(wc - l < ${FILE})
# generate random number in range 0-NUM
let X=${RANDOM} % ${NUM} + 1
# extract X-th line
sed -n ${X}p ${FILE}
11
Paolo Tedesco

Einzelne Bash-Linie:

sed -n $((1+$RANDOM%`wc -l test.txt | cut -f 1 -d ' '`))p test.txt

Leichtes Problem: Dateiname duplizieren.

4
asalamon74

Hier ist ein einfaches Python-Skript, das die Aufgabe erfüllt:

import random, sys
lines = open(sys.argv[1]).readlines()
print(lines[random.randrange(len(lines))])

Verwendungszweck:

python randline.py file_to_get_random_line_from
3
Adam Rosenfield

Eine andere Möglichkeit, ' awk ' zu verwenden

awk NR==$((${RANDOM} % `wc -l < file.name` + 1)) file.name
2
Baskar

Eine Lösung, die auch unter MacOSX funktioniert und auch unter Linux (?) Funktionieren sollte:

N=5
awk 'NR==FNR {lineN[$1]; next}(FNR in lineN)' <(jot -r $N 1 $(wc -l < $file)) $file 

Woher:

  • N ist die Anzahl der gewünschten Zeilen

  • NR==FNR {lineN[$1]; next}(FNR in lineN) file1 file2--> speichern Sie die in file1 geschriebenen Zeilennummern und drucken Sie dann die entsprechende Zeile in file2 aus.

  • jot -r $N 1 $(wc -l < $file) -> N Zahlen zufällig (-r) im Bereich (1, number_of_line_in_file) mit jot zeichnen. Die Prozessersetzung <() lässt sie wie eine Datei für den Interpreter aussehen, so im vorherigen Beispiel file1.
1
jrjc

Wenn Sie nur Vanilla sed und awk und ohne $ RANDOM verwenden, lautet ein einfacher, platzsparender und einigermaßen schneller "Einzeiler" für die Auswahl einer einzelnen Zeile pseudozufällig aus einer Datei namens FILENAME:

sed -n $(awk 'END {srand(); r=Rand()*NR; if (r<NR) {sub(/\..*/,"",r); r++;}; print r}' FILENAME)p FILENAME

(Dies funktioniert auch, wenn FILENAME leer ist. In diesem Fall wird keine Zeile ausgegeben.)

Ein möglicher Vorteil dieses Ansatzes besteht darin, dass Rand () nur einmal aufgerufen wird.

Wie @AdamKatz in den Kommentaren ausgeführt hat, besteht eine andere Möglichkeit darin, für jede Zeile Rand () aufzurufen:

awk 'Rand() * NR < 1 { line = $0 } END { print line }' FILENAME

(Ein einfacher Beweis für die Richtigkeit kann auf der Grundlage der Induktion gegeben werden.)

Vorbehalt über Rand()

"Bei den meisten awk-Implementierungen, einschließlich gawk, beginnt Rand () jedes Mal, wenn Sie awk ausführen, Zahlen aus derselben Startnummer oder demselben Startwert."

- https://www.gnu.org/software/gawk/manual/html_node/Numeric-Functions.html

0
peak

Hier ist, was ich entdecke, da mein Mac OS nicht alle einfachen Antworten verwendet. Ich habe den Befehl jot verwendet, um eine Zahl zu generieren, da die $ RANDOM-Variablenlösungen in meinem Test nicht sehr zufällig zu sein scheinen. Beim Testen meiner Lösung hatte ich große Unterschiede in den in der Ausgabe enthaltenen Lösungen.

  RANDOM1=`jot -r 1 1 235886`
   #range of jot ( 1 235886 ) found from earlier wc -w /usr/share/dict/web2
   echo $RANDOM1
   head -n $RANDOM1 /usr/share/dict/web2 | tail -n 1

Das Echo der Variablen besteht darin, ein Bild der generierten Zufallszahl zu erhalten.

0
dreday13
#!/bin/bash

IFS=$'\n' wordsArray=($(<$1))

numWords=${#wordsArray[@]}
sizeOfNumWords=${#numWords}

while [ True ]
do
    for ((i=0; i<$sizeOfNumWords; i++))
    do
        let ranNumArray[$i]=$(( ( $RANDOM % 10 )  + 1 ))-1
        ranNumStr="$ranNumStr${ranNumArray[$i]}"
    done
    if [ $ranNumStr -le $numWords ]
    then
        break
    fi
    ranNumStr=""
done

noLeadZeroStr=$((10#$ranNumStr))
echo ${wordsArray[$noLeadZeroStr]}
0
Ken