Estoy tratando de escribir un script de shell. La idea es seleccionar una sola línea al azar del archivo de texto y mostrarla como una notificación de escritorio de Ubuntu.
Pero quiero que se seleccionen diferentes líneas cada vez que ejecuto el script. ¿Hay alguna solución para hacer esto? No quiero todo el guión. Solo esa cosa simple solamente.
scripts
text-processing
Anandu M Das
fuente
fuente
Respuestas:
Puede usar la
shuf
utilidad para imprimir líneas aleatorias desde el archivo-n
: número de líneas para imprimirEjemplos:
fuente
n
indicar el número de líneas para imprimir. (es decir, si solo desea una o dos líneas). No es el número de línea (es decir, primera línea, segunda línea).date +%S
) en una variable x, y luego seleccionar esa línea x usando los comandoshead
ytail
del archivo de texto. De todos modos tu método es más fácil. Graciasshuf
está en coreutils, por lo que está disponible de forma predeterminada. Nota: carga el archivo de entrada en la memoria. Hay un algoritmo eficiente que no lo requiere .También puede usar el
sort
comando para obtener una línea aleatoria del archivo.fuente
sort -R
produce un resultado diferenteshuf -n1
oselect-random
si hay líneas duplicadas en la entrada. Ver el comentario de @ EliahKagan .Sólo por diversión, aquí hay una solución pura fiesta que no utiliza
shuf
,sort
,wc
,sed
,head
,tail
u otras herramientas externas.La única ventaja sobre la
shuf
variante es que es un poco más rápido, ya que es puro golpe. En mi máquina, para un archivo de 1000 líneas, lashuf
variante tarda aproximadamente 0.1 segundos, mientras que el siguiente script tarda aproximadamente 0.01 segundos;) Entonces, si bienshuf
es la variante más fácil y más corta, esta es más rápida.Honestamente, seguiría buscando la
shuf
solución, a menos que la alta eficiencia sea una preocupación importante.fuente
shuf
es mucho mejor de todos modos. Pensando en ello, no creo que pure bash sea en realidad más eficiente que usarshuf
, como escribí anteriormente. Puede haber una sobrecarga mínima (constante) al disparar una herramienta externa, pero luego ejecutará mach más rápido que bash interpretado. Así queshuf
ciertamente escala mejor. Entonces, digamos que el guión tiene un propósito educativo: es agradable ver que se puede hacer;)shuf
es específico de GNU Coreutils (por ejemplo, no en FreeBSD 10.0).sort -R
es portátil, pero resuelve un problema diferente (relacionado): las cadenas que aparecen como líneas múltiples tienen una probabilidad igual a las que aparecen solo una vez. (Por supuesto,wc
y otras utilidades aún podrían usarse). Creo que la principal limitación aquí es que esto nunca elige nada después de la línea 32768 (y se vuelve menos aleatorio algo antes).$((RANDOM<<15|RANDOM))
está en 0..2 ^ 30-1. @JFSebastian Esshuf
, nosort -R
, lo que sesga hacia entradas más frecuentes. Ponershuf -n 1
en lugar desort -R | head -n1
y comparar. (Por cierto, las iteraciones de 10 ^ 3 son más rápidas que 10 ^ 6 y aún así son suficientes para mostrar la diferencia). Vea también una demostración más áspera y visual y este poco de tontería que muestra que funciona en entradas grandes donde todas las cadenas son de alta frecuencia .dieharder
parece ser todos ceros. Asumiendo que esto no es simplemente un error extraño de mi parte, ¡eso ciertamente explicaría por qué no es aleatorio! ¿Obtiene datos atractivos si ejecutawhile echo $(( RANDOM << 17 | RANDOM << 2 | RANDOM >> 13 )); do :; done | perl -ne 'print pack "I>"' > out
durante un tiempo y luego examina el contenidoout
con un editor hexadecimal? (O visualizarla sin embargo otra cosa te gusta.) Consigo todos los ceros, yRANDOM
no es el culpable: consigo todos los ceros cuando sustituyo$(( RANDOM << 17 | RANDOM << 2 | RANDOM >> 13 ))
con100
, también.Digamos que tienes archivo
notifications.txt
. Necesitamos contar el número total de líneas, para determinar el rango del generador aleatorio:Vamos a escribir en la variable:
Ahora para generar un número de
0
a$LINE
usaremosRANDOM
variable.Vamos a escribirlo en la variable:
Ahora solo necesitamos imprimir este número de línea:
Acerca de ALEATORIO:
Asegúrese de que su archivo tenga menos de 32767 números de línea. Ver esto si necesita un generador aleatorio más grande que funcione de inmediato.
Ejemplo:
fuente
LINES=$(wc -l < file.txt); R_LINE=$((RANDOM % LINES)); sed -n "${R_LINE}p" file.txt
$RANDOM % n
puede sesgar su distribución aleatoria incluso si$RANDOM
está bien% n
un número aleatorio.Aquí hay un script de Python que selecciona una línea aleatoria de los archivos de entrada o stdin:
El algoritmo es O (n) -time, O (1) -space. Funciona para archivos de más de 32767 líneas. No carga archivos de entrada en la memoria. Lee cada línea de entrada exactamente una vez, es decir, puede canalizar contenido arbitrario de gran tamaño (pero finito). Aquí hay una explicación del algoritmo .
fuente
Estoy impresionado por el trabajo que hicieron Malte Skoruppa y otros, pero aquí hay una forma mucho más simple de hacerlo:
Como algunos han notado, $ RANDOM no es aleatorio. Sin embargo, el límite de tamaño de archivo de 32767 líneas se supera al unir $ RANDOM juntos según sea necesario.
fuente