web-dev-qa-db-fra.com

Quel est un moyen facile de lire une ligne aléatoire à partir d'un fichier en ligne de commande Unix?

Quel est un moyen facile de lire une ligne aléatoire à partir d'un fichier en ligne de commande Unix?

231
Newbie Prog

Vous pouvez utiliser shuf:

shuf -n 1 $FILE

Il existe également un utilitaire appelé rl. Dans Debian, c’est le paquet randomize-lines qui fait exactement ce que vous voulez, bien qu’il ne soit pas disponible dans toutes les distributions. Sur sa page d’accueil, il recommande en fait d’utiliser shuf (ce qui n’existait pas au moment de sa création, je crois). shuf fait partie de GNU coreutils, rl ne l’est pas.

rl -c 1 $FILE
343
unbeknown

Une autre alternative:

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

(J'aime encore mieux l'approche shuf ci-dessus - je ne savais même pas que cela existait et je n'aurais jamais trouvé cet outil seul)

61

C'est simple. 

cat file.txt | shuf -n 1

Ceci est un peu moins rapide que "shuf -n 1 fichier.txt".

25
Yokai

perlfaq5: Comment sélectionner une ligne au hasard dans un fichier? Voici un algorithme d'échantillonnage de réservoir du Camel Book:

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

Ceci présente un avantage significatif en termes d'espace par rapport à la lecture de l'ensemble du fichier. Vous pouvez trouver une preuve de cette méthode dans The Art of Computer Programming, Volume 2, Section 3.4.2, de Donald E. Knuth.

14
Tracker1

en utilisant un script bash:

#!/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

Ligne bash unique:

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

Petit problème: nom de fichier en double.

4
asalamon74

Voici un script Python simple qui fera le travail:

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

Usage:

python randline.py file_to_get_random_line_from
3
Adam Rosenfield

Une autre façon en utilisant ' awk '

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

Une solution qui fonctionne aussi sur MacOSX, et devrait aussi fonctionner sur Linux (?):

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

Où:

  • N est le nombre de lignes aléatoires que vous voulez

  • NR==FNR {lineN[$1]; next}(FNR in lineN) file1 file2--> enregistrez les numéros de ligne écrits en file1 puis imprimez la ligne correspondante en file2

  • jot -r $N 1 $(wc -l < $file) -> draw N nombres aléatoirement (-r) dans la plage (1, number_of_line_in_file) avec jot. Le processus de substitution <() le fera ressembler à un fichier pour l'interpréteur, donc file1 dans l'exemple précédent.
1
jrjc

En n'utilisant que Vanilla sed et awk, et sans utiliser $ RANDOM, vous trouverez ci-dessous une "ligne unique" simple, peu encombrante et assez rapide pour sélectionner une seule ligne pseudo-aléatoire à partir d'un fichier nommé FILENAME:

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

(Cela fonctionne même si FILENAME est vide, auquel cas aucune ligne n'est émise.)

Un avantage possible de cette approche est qu’elle n’appelle qu'une fois Rand ().

Comme l'a souligné @AdamKatz dans les commentaires, une autre possibilité serait d'appeler Rand () pour chaque ligne:

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

(Une simple preuve d'exactitude peut être donnée sur la base de l'induction.)

Mise en garde sur Rand()

"Dans la plupart des implémentations awk, y compris gawk, Rand () commence à générer des nombres à partir du même numéro de départ, ou graine, à chaque fois que vous exécutez awk."

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

0
peak

Voici ce que je découvre car mon Mac OS n’utilise pas toutes les réponses faciles. J'ai utilisé la commande jot pour générer un nombre car la solution de variable $ RANDOM ne semble pas être très aléatoire dans mon test. Lors du test de ma solution, les solutions fournies dans la sortie étaient très différentes.

  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

L'écho de la variable est d'obtenir un visuel du nombre aléatoire généré.

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