Was ist eine einfache Möglichkeit, eine zufällige Zeile aus einer Datei in der Unix-Befehlszeile zu lesen?
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
Eine andere Alternative:
head -$((${RANDOM} % `wc -l < file` + 1)) file | tail -1
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".
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.
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}
Einzelne Bash-Linie:
sed -n $((1+$RANDOM%`wc -l test.txt | cut -f 1 -d ' '`))p test.txt
Leichtes Problem: Dateiname duplizieren.
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
Eine andere Möglichkeit, ' awk ' zu verwenden
awk NR==$((${RANDOM} % `wc -l < file.name` + 1)) file.name
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
.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.)
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
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.
#!/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]}