linux - script - ¿Cuál es una forma fácil de leer una línea aleatoria de un archivo en la línea de comandos de Unix?
lista completa de comandos linux pdf (13)
Aquí hay un script de Python simple que hará el trabajo:
import random, sys
lines = open(sys.argv[1]).readlines()
print(lines[random.randrange(len(lines))])
Uso:
python randline.py file_to_get_random_line_from
¿Cuál es una forma fácil de leer una línea aleatoria de un archivo en la línea de comandos de Unix?
Esto es lo que descubrí, ya que mi Mac OS no usa todas las respuestas fáciles. Utilicé el comando jot para generar un número, ya que las soluciones de la variable $ RANDOM no parecen ser muy aleatorias en mi prueba. Al probar mi solución, tuve una gran variación en las soluciones proporcionadas en la salida.
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
El eco de la variable es obtener una visualización del número aleatorio generado.
Esto es simple.
cat file.txt | shuf -n 1
Por supuesto, esto es solo un poco más lento que el "shuf -n 1 file.txt" por sí mismo.
Línea de bash único:
sed -n $((1+$RANDOM%`wc -l test.txt | cut -f 1 -d '' ''`))p test.txt
Problema leve: duplicar nombre de archivo.
Otra alternativa:
head -$((${RANDOM} % `wc -l < file` + 1)) file | tail -1
Otra forma de usar '' awk ''
awk NR==$((${RANDOM} % `wc -l < file.name` + 1)) file.name
Una solución que también funciona en MacOSX, y también debería funcionar en Linux (?):
N=5
awk ''NR==FNR {lineN[$1]; next}(FNR in lineN)'' <(jot -r $N 1 $(wc -l < $file)) $file
Dónde:
N
es el número de líneas aleatorias que deseasNR==FNR {lineN[$1]; next}(FNR in lineN) file1 file2
NR==FNR {lineN[$1]; next}(FNR in lineN) file1 file2
-> guardar números de línea escritos enfile1
y luego imprimir la línea correspondiente enfile2
-
jot -r $N 1 $(wc -l < $file)
-> dibujaN
números al azar (-r
) en el rango(1, number_of_line_in_file)
conjot
. La sustitución del proceso<()
hará que se vea como un archivo para el intérprete, por lo quefile1
en el ejemplo anterior.
Usando solo vainilla sed y awk, y sin usar $ RANDOM, un sencillo "de una sola línea" para ahorrar espacio y razonablemente rápido para seleccionar una sola línea de forma pseudoaleatoria desde un archivo llamado FILENAME es el siguiente:
sed -n $(awk ''END {srand(); r=rand()*NR; if (r<NR) {sub(//..*/,"",r); r++;}; print r}'' FILENAME)p FILENAME
(Esto funciona incluso si FILENAME está vacío, en cuyo caso no se emite ninguna línea).
Una posible ventaja de este enfoque es que solo llama a rand () una vez.
Como lo señaló @AdamKatz en los comentarios, otra posibilidad sería llamar a rand () para cada línea:
awk ''rand() * NR < 1 { line = $0 } END { print line }'' FILENAME
(Se puede dar una prueba simple de corrección basada en la inducción).
Advertencia sobre rand()
"En la mayoría de las implementaciones de awk, incluyendo gawk, rand () comienza a generar números desde el mismo número de inicio, o semilla, cada vez que ejecutas awk".
- https://www.gnu.org/software/gawk/manual/html_node/Numeric-Functions.html
utilizando 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}
perlfaq5: ¿Cómo selecciono una línea aleatoria de un archivo? Aquí hay un algoritmo de muestreo de yacimiento del Libro de camellos:
$ perl -e ''srand; rand($.) < 1 && ($line = $_) while <>; print $line;'' file
Esto tiene una ventaja significativa en el espacio sobre la lectura de todo el archivo. Puede encontrar una prueba de este método en El arte de la programación de computadoras, Volumen 2, Sección 3.4.2, por Donald E. Knuth.
Puedes usar shuf
:
shuf -n 1 $FILE
También hay una utilidad llamada rl
. En Debian, está en el paquete de randomize-lines
que hace exactamente lo que usted quiere, aunque no está disponible en todas las distribuciones. En su página de inicio, en realidad recomienda el uso de shuf
(que no existía cuando se creó, creo). shuf
es parte de los coreutils de GNU, rl
no lo es.
rl -c 1 $FILE
#!/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]}
sort --random-sort $FILE | head -n 1
(Aunque me gusta el enfoque de Shuf, incluso mejor. Ni siquiera sabía que existía y nunca hubiera encontrado esa herramienta por mi cuenta)