Cuando usando una aplicación nos autocompleta el texto, nos subraya una palabra o nos dice que algo está incorrectamente escrito, no es magia, es que esa aplicación hace uso de un diccionario.
Aunque hay aplicaciones que tienen diccionarios propios, el sistema también tiene al menos uno genérico del que podemos hacer uso o podemos usarlo como base para añadirle nuevas palabras.
En Ubuntu, este diccionario está en:
/usr/share/dict/spanish
Pero no necesariamente todas las distribuciones tienen por qué guardar el diccionario de español en esa dirección, por lo que podemos buscar en nuestro sistema con:
find /usr -iname spanish | grep dict
Y nos dirá la dirección en el arbol de directorios del sistema de nuestro diccionario.
Ya sabemos cómo seleccionar aleatoriamente una tipografía para incluir texto en ImageMagick, pero nos puede ocurrir que, al ser aleatoria esa selección, nos elija una tipografía que sean dibujos, signos matemáticos o cualquier otra tipografía que no sea de letras, también nos puede mostrar una tipografía con un alfabeto distinto al nuestro o que no muestre bien algunos caracteres.
Yo siempre me fijo en cuatro caracteres clave: apertura de interrogación y exclamación, vocales con tilde y eñes.
Así pues, voy a usar una cadena de caracteres que tenga interrogaciones, una vocal con tilde y una eñe:
¿Leña? ¡Porrón!
Y como quiero ver qué tipografías que tengo instaladas en cada máquina muestran correctamente estos caracteres, hago los siguientes pasos:
#!/bin/bash
directoriotemporaltipografias="tipografias"
if [ ! -d directoriotemporaltipografias ]
then
mkdir $directoriotemporaltipografias
fi
for tipografia in $(convert -list font | grep "Font" | cut -d " " -f 4)
do
convert -pointsize 100 -font $tipografia label:"¿Leña? ¡Porrón!" $directoriotemporaltipografias/$tipografia.jpg
done
Veamos qué es lo que hace:
Indico que es un script en bash:
#!/bin/bash
Que el directorio con el que voy a trabajar se llama "tipografias", pero lo meto en una variable por si por cualquier motivo quiero cambiar de directorio:
directoriotemporaltipografias="tipografias"
Compruebo si existe o no ese directorio y si no existe, lo creo:if [ ! -d directoriotemporaltipografias ]
then
mkdir $directoriotemporaltipografias
fi
Hago un bucle en el que recorre todas las tipografías tal como vimos en el artículo anterior sobre tipografías en ImageMagick: y le digo que me genere una imagen por cada tipografía con la cadena antes indicada de "¿Leña? ¡Porrón!" guardando esas imágenes con el nombre de la tipografía utilizada en el directorio creado para tal efecto:for tipografia in $(convert -list font | grep "Font" | cut -d " " -f 4)
do
convert -pointsize 100 -font $tipografia label:"¿Leña? ¡Porrón!" $directoriotemporaltipografias/$tipografia.jpg
done
Con esto, tengo un directorio lleno de imágenes con cadenas de texto. Abro el directorio con un navegador de ficheros que muestre una previsualización de cada imagen y selecciono todas las imágenes que no me interesan por el motivo que sea, que generalmente es porque no escribe bien todos los caracteres indicados:
Otras veces es porque, aunque muestre correctamente los caracteres, no me parecen lo suficientemente legibles o son muy específicos de una determinada fecha: navideños, de Hallowen, con nieve...
Una vez borrados los que en una primera ronda en bruto me han parecido que no cubren mis necesidades (ojo, que cuando seleccionamos aleatoriamente una tipografía es bastante arriesgado poner a trabajar ese script y desentendernos, por lo que es mejor que, en caso de duda, borrar el fichero), paso a una segunda fase en la que miro una por una las tipografías.
A veces nos encontramos que una tipografía escribe correctamente los caracteres pero no nos queremos arriesgar a que un script la seleccione sin nuestra aprobación:
Estas tipografías muestran todos los caracteres, pero quizá no encajen en todos los contextos, por lo que las borro también.
Y una vez que he borrado todo lo que sobra, ejecuto un segundo script:
#!/bin/bash
directoriotemporaltipografias="tipografias"
for fichero in $(ls $directoriotemporaltipografias)
do
echo ${fichero%.*} >> tipografiasausar.txt
done
rm -r $directoriotemporaltipografias
rmdir $directoriotemporaltipografias
En el que le indico:
Que es un script bash:
#!/bin/bash
Que recoja los ficheros de un determinado directorio:directoriotemporaltipografias="tipografias"
Que recorra ese directorio fichero a fichero y quite la extensión de esos ficheros ${fichero%.*} e incluya el nombre sin extensión en un fichero de texto llamado tipografiasausar.txt añadiendo en cada pasada de for cada tipografía al texto ya existente en ese fichero (>>) for fichero in $(ls $directoriotemporaltipografias)
do
echo ${fichero%.*} >> tipografiasausar.txt
done
Que borre el contenido de ese directorio y el propio directorio para que no ocupe espacio en disco ni moleste una vez hecha la selección. rm -r $directoriotemporaltipografias
rmdir $directoriotemporaltipografias
Una vez creado el fichero tipografiasausar.txt para seleccionar aleatoriamente una línea de ese fichero lo podemos hacer con shuf. Así:
tipografia=$(shuf -n 1 tipografiasausar.txt)
Y así quedaría un script de ejemplo:
#!/bin/bash
tipografia=$(shuf -n 1 tipografiasausar.txt)
convert -pointsize 100 -fill Blue -font $tipografia label:"Automaticen\ny sean felices" automaticen.png
En ImageMagick tenemos el parámetro -list que lista los valores que pueden recibir algunos parámetros.
Uno de los parámetros del que se puede listar los valores que puede recibir es font, que es el parámetro que permite seleccionar la tipografía con la que escribir un texto con annotate o label, así pues, si escribimos:
convert -list font
convert nos mostará las tipografías de nuestro sistema con una serie de datos más, como la familia, la dirección...
Font: Zoidal-BRK
family: Zoidal BRK
style: Normal
stretch: Normal
weight: 400
glyphs: /usr/share/fonts/truetype/aenigma/zoidal.ttf
Font: Zrnic
family: Zrnic
style: Normal
stretch: Normal
weight: 400
glyphs: /usr/share/fonts/truetype/larabie/zrnic___.ttf
Font: Zurklez-Outline-BRK
family: Zurklez Outline BRK
style: Normal
stretch: Normal
weight: 400
glyphs: /usr/share/fonts/truetype/aenigma/zurklezo.ttf
Font: Zurklez-Solid-BRK
family: Zurklez Solid BRK
style: Normal
stretch: Normal
weight: 400
glyphs: /usr/share/fonts/truetype/aenigma/zurklezs.ttf
Font: Æ-Systematic-TT-BRK
family: Æ Systematic TT BRK
style: Normal
stretch: Normal
weight: 400
glyphs: /usr/share/fonts/truetype/aenigma/aesymatt.ttf
Font: Ænigma-Scrawl-4-BRK
family: Ænigma Scrawl 4 BRK
style: Normal
stretch: Normal
weight: 400
glyphs: /usr/share/fonts/truetype/aenigma/aescrawl.ttf
Sin embargo, pese a que convert muestra toda esa información el nombre de la tipografía que vamos a usar a la hora de generar un texto con ImageMagick es el que sucede a "Font:". Así pues, si lo que queremos es saber el nombre con el que podremos invocar a las tipografías desde convert para añadir textos en nuestras imágenes o generar imágenes con texto, podremos listar únicamente esas líneas. Y aquí es donde llamamos a nuestro amigo grep:
convert -list font | grep Font
Font: Zakenstein-Rotalic
Font: Zekton
Font: Zekton-Bold
Font: Zekton-Bold-Italic
Font: Zekton-Dots
Font: Zekton-Italic
Font: Zelda-DX-TT-BRK
Font: Zenith-BRK
Font: Zephyrean-BRK
Font: Zephyrean-Gust-BRK
Font: Zero-Threes
Font: Zero-Twos
Font: Zero-Velocity-BRK
Font: ZeroHour
Font: Zirconia-BRK
Font: Zirconia-Cubic-BRK
Font: Zodillinstrisstirust
Font: Zoetrope-BRK
Font: Zoidal-BRK
Font: Zrnic
Font: Zurklez-Outline-BRK
Font: Zurklez-Solid-BRK
Font: Æ-Systematic-TT-BRK
Font: Ænigma-Scrawl-4-BRK
Otra fórmula sería extraer la columna donde están las cadenas de texto que contienen los nombres de las tipografías, el comando cut ayuda mucho en esta tarea:
convert -list font | grep Font | cut -d " " -f 4
Con estos parámetros le decimos a cut, que es un comando que "corta" cadenas, que el separador es un espacio en blanco con -d " ".
Del mismo modo, le podríamos indicar que el separador de columnas es cualqueir otro caracter o cadena de caracteres. El parámetro -f lo que indica es el número de la columna que ha de mostar, en este caso, la cuarta. Veamos:
Zekton
Zekton-Bold
Zekton-Bold-Italic
Zekton-Dots
Zekton-Italic
Zelda-DX-TT-BRK
Zenith-BRK Zephyrean-BRK
Zephyrean-Gust-BRK
Zero-Threes Zero-Twos
Zero-Velocity-BRK
ZeroHour Zirconia-BRK
Zirconia-Cubic-BRK
Zodillinstrisstirust
Zoetrope-BRK
Zoidal-BRK
Zrnic
Zurklez-Outline-BRK
Zurklez-Solid-BRK
Æ-Systematic-TT-BRK
Ænigma-Scrawl-4-BRK
Y ahora que ya tenemos el listado limpio, únicamente tenemos que elegir una cadena al azar. Lo podemos hacer con shuf: convert -list font | grep Font | cut -d " " -f 4 | shuf -n 1
Intersect-O-BRK
Y si lo probamos muchas veces, veremos que el resultado es aleatorio, por lo que cada vez que ejecutemos esa instrucción será distinta:
Y dentro de un script, el uso sería igual:
#!/bin/bash
tipografia=$(convert -list font | grep Font | cut -d " " -f 4 | shuf -n 1)
echo "La tipografía seleccionada de forma aleatoria ha salido: "$tipografia
Veamos si así funciona:
Como vemos, cada vez que ejecutamos el script nos muestra una tipografía distinta.
Y ahora, vamos a usarlo con ImageMagick para generar una imagen con una tipografía aleatoria:
#!/bin/bash
tipografia=$(convert -list font | grep Font | cut -d " " -f 4 | shuf -n 1)
convert -pointsize 100 -font $tipografia label:"Disfruten del\nSoftware Libre" disfruten.png
Y vamos a hacer un for para comprobar que realmente genera imágenes con distintas tipografías:
#!/bin/bash
for i in $(seq 1 3)
do
tipografia=$(convert -list font | grep Font | cut -d " " -f 4 | shuf -n 1)
convert -pointsize 100 -font $tipografia label:"Disfruten del\nSoftware Libre" disfruten$i.png
done
Vista la forma básica de generar textos con tipografías aleatorias, veremos también cómo hacer una selección previa de las tipografías para usar aquellas tipografías que se ajusten a nuestras necesidades.
Estoy haciendo una serie de tutoriales de GIMP 2.10 y quería mostrar cómo van cambiando las imágenes al cambiar los valores de los deslizadores de las distintas herramientas que forman GIMP.
Una opción es capturar la pantalla con recordMyDesktop o ffmpeg y colgarlo tal cual. El problema de esto es que el entorno de GIMP ocupa un espacio que hace que la imagen se vea pequeña. Así que prefiero hacer un efecto PiP (Picture in Picture). Es decir, superponer una imagen, en este caso, la caja de la herramienta sobre otra imagen más grande, en este caso, la imagen que va cambiando según los valores dados en la caja de la herramienta.
Podría capturar la pantalla y con un editor de vídeo, por ejemplo, Kdenlive, duplicar la pista y hacer dos "crops": uno con la imagen y otro con la herramienta, superponer ambas y montar el vídeo. Aparte de que el proceso de edición es farragoso, debería también hacer muchas veces clic con el ratón. Demasiado trabajo... seguro que ImageMagick me permite hacer el mismo resultado con menos esfuerzo. Veamos cómo hacerlo:
1.- Para el primer ejemplo, he cogido la primera herramienta del menú de Color de GIMP. Y me aparece que los deslizadores van del -100 al 100. Así que, en lugar de hacer 201 clic con el ratón, voy a hacer un bucle con una secuencia del 0 al 200.
2.- En cada iteración voy a capturar la pantalla completa con import y hacer dos recortes con crop, por un lado, la imagen que va cambiando y por otro, la herramienta de turno, en este caso, "Balance de color".
3.- Como quiero que el vídeo esté en formato HD, paso la imagen a un tamaño de 1920x1080 píxeles.
4.- Superpongo las imágenes con composite y hago clic para aumentar el valor.
5.- Le digo a ffmpeg que haga un vídeo con todos los fotogramas
6.- Y borro las imágenes sobrantes
Ya he escrito previamente sobre todas las instrucciones de este script a excepción de xdotool, que es un comando para simular el manejo del ratón a través de línea de comandos. Permite cliquear con los distintos botones, mover la ruleta, mover el cursor, hacer doble clic... En este caso, como únicamente quiero que haga un clic con el botón izquierdo, usaré:
xdotool click 1
Así es como queda el script:
#!/bin/bash
for i in $(seq 0 200)
do
import -w root pantallazo.png
convert pantallazo.png -crop 1308x735+172+214 lienzo$1$i.png
convert pantallazo.png -crop 412x501+1497+242 -background Transparent -gravity Center -extent 600x600 deslizador$1$i.png
convert lienzo$1$i.png -resize 1920x1080 base.png
composite -gravity SouthEast deslizador$1$i.png base.png png:-
xdotool click 1
done | ffmpeg -f image2pipe -i - videos/$1.mp4
rm lienzo*
rm deslizador*
Y así queda el resultado:
Podemos descargar en nuestro ordenador todos los tuits de un usuario de Twitter pinchando uno a uno, dándole botón derecho y guardando la página... o haciendo un pequeño script.
Veamos paso a paso cómo hacerlo:
Acotar la búsqueda
Vamos a usar la cuenta de @LinuxCenterEs como ejemplo, así que vamos a mirar cuándo se unió a twitter, a qué fecha estamos y usaremos esos dos datos para delimitar el rango temporal desde donde hay que descargar.
Para saber la fecha actual, usaremos date.
Para saber la fecha en la que se unió un usuario a Twitter, tenemos que mirar en el código fuente. Para saber qué cadena buscamos, vamos a mirar primero la fecha en el perfil del usuario:
Después buscamos esa cadena en el código fuente y miramos a qué clase o div pertenece:
Y comprobamos si esa clase se utiliza únicamente para ese dato:
Ya tenemos la pista con la que extraer la cadena de la fecha en la que se unió el usuario a Twitter.
Ahora tenemos que descargar la página, buscar la línea y extraer únicamente la cadena:
#!/bin/bash
wget https://twitter.com/$1 -O $1.html
lineafecha=$(cat $i.html | grep "ProfileHeaderCard-joinDateText js-tooltip u-dir")
echo $lineafecha
Voy a comprobar si funciona hasta aquí:
Por ahora parece que vamos bien. Ahora vamos a limpiar la cadena.
Ojo, tenemos que limpiar acorde con el idioma de nuestro sistema. Si, por ejemplo, tuviésemos el sistema en inglés, la cadena es distinta:
Veamos cómo llevamos el script hasta ahora:
#!/bin/bash
wget https://twitter.com/$1 -O $1.html
lineafecha=$(cat $i.html | grep "ProfileHeaderCard-joinDateText js-tooltip u-dir")
mescomienzo=$(echo $lineafecha | cut -d " " -f 13)
anocomienzo=$(echo $lineafecha | cut -d " " -f 15 | cut -d "<" -f 1)
case $mescomienzo in
enero)
mescomienzo="01"
;;
febrero)
mescomienzo="02"
;;
marzo)
mescomienzo="03"
;;
abril)
mescomienzo="04"
;;
mayo)
mescomienzo="05"
;;
junio)
mescomienzo="06"
;;
julio)
mescomienzo="07"
;;
agosto)
mescomienzo="08"
;;
septiembre)
mescomienzo="09"
;;
octubre)
mescomienzo="10"
;;
noviembre)
mescomienzo="11"
;;
diciembre)
mescomienzo="12"
;;
esac
mesfinal=$(date +%m)
anofinal=$(date +%Y)
echo "Las fechas a buscar son desde el "$mescomienzo" de "$anocomienzo" hasta el "$mesfinal" de "$anofinal
Y veamos si funciona bien:
Pues parece que vamos por buen camino. Así que seguimos:
Ahora que ya sabemos las fechas que hemos de recorrer, vamos a ver cómo explotar este dato, tal como adelanté en un hilo de twitter: https://twitter.com/hacemoswebserie/status/1040037466802151426
Antes de seguir, comentaré que la cadena para hacer una búsqueda de los tuits que un determinado usuario de Twitter ha publicado entre dos fechas es:
"https://twitter.com/search?q=From%3A"$1"%20since%3A"$anocomienzo"-"$mescomienzo"-"$diacomienzo"%20until%3A"$anofinal"-"$mesfinal"-"$diafinal"&src=typd"
Y siempre es así. Simplemente cambiando las variables. Pero lo mejor de todo, es que todas las redes sociales siguen patrones similares, por lo que este tutorial es extrapolable a cualquier otra red social o cualquier otra búsqueda dentro de Twitter.
Y una advertencia, a veces si hacemos muchas descargas desde una misma IP o desde un mismo navegador, puede que nos bloquee ese servidor las descargas y no sirva nuestro script. Varias soluciones para esto:
Pero si vamos a hacer un uso moderado, como en este ejemplo en el que descargarnos los tuits de un único usuario, no debería darnos más problema que no nos deja descargar con wget si no le indicamos un "user agent" distinto.
Así que le indicaremos a wget que, por ejemplo, usamos Firefox con Windows. Lo haremos con: wget --user-agent="Mozilla/5.0 (Windows; U; Windows NT 5.1; pl; rv:1.9.2.3) Gecko/20100401 Lightningquail/3.6.3"
Y nos quedaría un script así:
#!/bin/bash
lineafecha=$(cat $i.html | grep "ProfileHeaderCard-joinDateText js-tooltip u-dir")
mescomienzo=$(echo $lineafecha | cut -d " " -f 13)
anocomienzo=$(echo $lineafecha | cut -d " " -f 15 | cut -d "<" -f 1)
case $mescomienzo in
enero)
mescomienzo="01"
;;
febrero)
mescomienzo="02"
;;
marzo)
mescomienzo="03"
;;
abril)
mescomienzo="04"
;;
mayo)
mescomienzo="05"
;;
junio)
mescomienzo="06"
;;
julio)
mescomienzo="07"
;;
agosto)
mescomienzo="08"
;;
septiembre)
mescomienzo="09"
;;
octubre)
mescomienzo="10"
;;
noviembre)
mescomienzo="11"
;;
diciembre)
mescomienzo="12"
;;
esac
mesfinal=$(date +%m)
anofinal=$(date +%Y)
for a in $(seq $anocomienzo $anofinal)
do
for m in $(seq 1 12)
do
if [ $m -lt 10 ]
then
m="0"$m
fi
cadena="https://twitter.com/search?q=From%3A"$1"%20since%3A"$a"-"$m"-01%20until%3A"$a"-"$m"-31&src=typd"
wget --user-agent="Mozilla/5.0 (Windows; U; Windows NT 5.1; pl; rv:1.9.2.3) Gecko/20100401 Lightningquail/3.6.3" $cadena -O "tuits-"$m"-"$a".html"
done
done
Sobre esta base, podemos seguir evolucionando, como definir que el primer año sólo descargue a partir del mes de comienzo, que el último año sólo descargue hasta el mes de final, que descargue los tuits día a día... Eso a gusto de cada uno.
En cuanto a usos, una vez descargados todos los tuits, podemos analizar las candenas con múltiples fines, desde hacer análisis de mercados, comprobar el número de adjetivos, sustantivos, pronombres... que utiliza ese usuario, o, por ejemplo, saber cuántas veces nos cita ese usuario:
Veamos cómo se porta LinuxCenterEs conmigo:
#!/bin/bash
let contador=0
for i in $(ls *.html)
do
let nominaciones=$(cat $i | grep -c hacemoswebserie)
let contador=$contador+$nominaciones
let nominaciones=0
done
echo "Te han citado "$contador" veces."
Veamos si funciona:
Y como funciona todo hasta aquí, aquí dejo el artículo. Ahora es tarea de cada usuario el adaptar este artículo a sus intereses. Las bases están sentadas... que la evolución haga el resto.
Para trabajar con fechas y con horas en un script, o en la consola, tenemos el comando date. Veamos su uso y algunos de sus parámetros más usuales.
Si únicamente escribimos date, nos devuelve el día de la semana indicado con tres caracteres; el mes, indicado de nuevo con tres caracteres; la hora completa con hora, minutos y segundos; el huso horario de nuestro ordenador y el año actual.
Parámetros usuales:
date +%H -> indica la hora (sin minutos) actual
date +%M -> indica los minutos actuales
date +%H:%M -> indica la hora y minutos actuales
date +%d -> indica qué día del mes es hoy
date +%m -> indica el mes actual en número
date +%B -> indica el mes actual en letras, con la palabra completa
date +%Y -> indica el año actual
Ejemplo:
echo "Hoy es el "$(date +%D)" de "$(date +%B)" de "$(date +%y)
Puede que te preguntes si te tienes que aprender todas esas opciones para hacer un uso eficaz de date. No. No hace falta. GNU/Linux es un sistema que permite optimizar todos los recursos... incluída la memoria de los usuarios. Con un sencillo script, podemos indicarle a un array que incluya las letras mayúsculas, a otro que incluya las minúsculas, concatene ambos arrays y lo recorra devolviendo el restultado de pasarle esos parámetros a date.
Hecho esto, lo ejecutamos y vemos qué parámetros son los que más nos interesan... incluso vemos qué letras no son parámetros de date.
Aquí dejo el script:
#!/bin/bash
minusculas=({a..z})
mayusculas=({A..Z})
letras=($(echo ${minusculas[*]}) $(echo ${mayusculas[*]}))
for i in $(seq 0 ${#letras[*]})
do
echo "date +"${letras[$i]}"%: "$(date +%${letras[$i]})
done
Ya hemos visto que, dado que %$valor lo que hace es calcular el resto de la división entre la cifra que precede a % (dividendo) y la cifra que sucede a % (divisor), $RANDOM%limitesuperior no vale para generar números aleatorios de forma fideligna (a no ser que seamos trileros, pero en este caso no buscamos una verdadera aleatoriedad).
También hemos visto que shuf sí que sirve para crear órdenes aleatorios. Y ahora vamos a ver cómo usar shuf para generar números aleatorios.
Veamos cómo usar shuf en el primer ejemplo que usé en contra de $RANDOM: una aleatoriedad dos valores. Pero antes de ello, vuelvo a remarcar que shuf no genera nada, sino que hace un orden aleatorio de una lista. Así que primero hay que generar una lista y luego ordenar aleatoriamente con shuf.
Veamos varias formas de hacerlo:
En un fichero auxiliar:
#/bin/bash
let comienzo=0
let final=1
for i in $(seq $comienzo $final)
do
echo $i >> numeros.txt
done
Y ahora podemos ejecutarlo y luego ordenar con shuf. Veamos a ver si la aleatoriedad es tal:
En este pantallazo vemos que de 12 tiradas, han salido siete veces 0 y cinco veces 1. Está dentro de la normalidad. Pero vamos a ver qué ocurre si tiramos mil veces la moneda:
#/bin/bash
let ceros=0
let unos=0
for i in $(seq 1 1000)
do
let moneda=$(shuf -n1 numeros.txt)
if [ $moneda -eq 0 ]
then
let ceros++
else
let unos++
fi
done
echo "El número de ceros que ha salido es: "$ceros
echo "El número de unos que ha salido es: "$unos
Y lo comprobamos (vuelvo a poner pantallazo para que se vea que no hay trampa ni cartón):
¡Incluso me ha llegado a dar un empate de 500 a 500!
Visto que shuf es más válido en este caso, vamos a ver cómo generar una lista aleatoria con shuf. Compruebo en el mismo script para evitar hacer un artículo excesivamente largo:
#/bin/bash
let ceros=0
let unos=0
for i in $(seq 1 1000)
do
numeros=$(shuf -i 0-1)
if [[ ${numeros:0:1} == "0" ]]
then
let ceros++
else
let unos++
fi
done
echo "El número de ceros que ha salido es: "$ceros
echo "El número de unos que ha salido es: "$unos
Funciona... y de nuevo hemos tenido un empate a 500 en una tirada.
Pero ahora te puedes preguntar, por qué si existe el parámetro -i en shuf para generar una lista con orden aleatorio y el parámetro -n para extraer un número determinado de elementos, ¿por qué no lo usas en la misma línea?
No te falta razón para pensarlo, pero quería mostrar distintas formas de lanzar la moneda. Y hacer un artículo evolutivo que acabase con la mejor opción:
#/bin/bash
let ceros=0
let unos=0
for i in $(seq 1 1000)
do
numeros=$(shuf -i 0-1 -n 1)
if [[ $numeros == "0" ]]
then
let ceros++
else
let unos++
fi
done
echo "El número de ceros que ha salido es: "$ceros
echo "El número de unos que ha salido es: "$unos
Y vuelve a funcionar... incluso me ha dado otro empate a 500.
¿Y si en lugar de tirar a cara o cruz hacemos un rango mayor, por ejemplo de 0 a 1000?
Simplemente le cambiamos el rango en -i. Y si además, para comprobar si funciona, vamos a aumentar el número de tiradas.
#/bin/bash
let ceros=0
let quinientos=0
let miles=0
for i in $(seq 1 10000)
do
numeros=$(shuf -i 0-1000 -n 1)
if [[ $numeros == "0" ]]
then
let ceros++
elif [[ $numeros == "500" ]]
then
let quinientos++
elif [[ $numeros == "1000" ]]
then
let miles++
fi
done
echo "El número de ceros que ha salido es: "$ceros
echo "El número de quinientos que ha salido es: "$quinientos
echo "El número de miles que ha salido es: "$miles
Y al probarlo, da unos resultados tales como:
Que son unos resultados que son totalmente coherentes dentro de lo que es la aleatoriedad por lo que podemos decir que la mejor forma para generar un número aleatorio en Bash es
shuf -i $limiteinferior-$limitesuperior -n 1
En tres artículos he estado argumentando en contra del uso de $RANDOM para generar números aleatorios:
El mito de $((RANDOM%$limitesuperior))
Más sobre la "aleatoriedad" de $RANDOM
Dados cargados en $RANDOM
Pero es poco honesto criticar algo sin aportar una solución, así que aquí voy a explicar el uso de shuf y en otro artículo explicaré varias formas de usar shuf para generar números aleatorios.
shuf se puede usar para ordenar aleatoriamente un fichero de texto:
shuf fichero.txt
Como vemos al usar cat, las palabras de fichero.txt tenían un orden que, al usar shuf, han cambiado de orden.
También shuf permite seleccionar X elementos de una lista. Ya lo hemos usado otras veces, como al elegir aleatoriamente una tipografía o un color con ImageMagick. Pero veamos con el ejemplo anterior:
shuf -n2 fichero
Con el parámetro -n$numerodelineas muestra el número de líneas incado como valor a -n.
Otra forma de usar shuf es recibiendo una lista desde la salida de otro fichero.
Veamos un ejemplo creando una serie de ficheros en un directorio y luego seleccionando uno al azar recogiendo con shuf la salida de ls.
Otro parámetro muy interesante es -o para especificar un fichero donde guardar la salida de shuf. Evolucionemos la instrucción anterior:
ls | shuf -o ordenaleatorio.txt
¿Os han pedido alguna vez que tuiteeis algún gif de alguna película? A mi, sí. Hace unos minutos. Así que ya que voy a hacer un gif de una de mis películas favoritas, os cuento cómo hacerlo. Pero no es necesario que os pidan un gif de una película, si queréis hacer un gif a partir de un vídeo de YouTube, podéis seguir paso a paso este artículo. En caso de que tengáis el vídeo en vuestro ordenador, podéis obviar la parte de la descarga del vídeo.
Para descargar un vídeo de YouTube, o casi de cualquier plataforma de vídeo, incluídas muchas plataformas de vídeos para adultos, tenemos un comando súper eficiente para ello: youtube-dl. Su uso más básico es para descargar un vídeo (si quieren que escriba un artículo explicando cómo descargar sólo audio o una lista de vídeos, escríbanlo en los comentarios). Y para descargar un vídeo no necesitamos ni parámetros ni nada más que el comando y la url del vídeo. Como yo quiero tuitear sobre Machete (como digo, me han pedido un gif de una de mis películas favoritas, así que elijo esta escena de Machete):
https://www.youtube.com/watch?v=DTyeEB-ra7w
Y lo descargo con:
youtube-dl https://www.youtube.com/watch?v=DTyeEB-ra7w
Como he visto el vídeo de YouTube y sé que la parte de la que quiero extraer los fotogramas va de 00:14 a 00:21 uso el comando:
ffmpeg -i Machete\ improvises-DTyeEB-ra7w.mp4 -ss 00:14 -t 8 machete%04d.jpg
Voy a escribir dos frases: "Machete no manda mensajes" y "Machete improvisa". Para ver sobre qué fotogramas escribo cada una de las frases, voy a mirar dónde está el cambio de plano:
Hasta el fotograma machete0056.jpg voy a poner "Machete no manda mensajes" y en el resto, hasta el 200, "Machete improvisa":
#!/bin/bash
for i in $(seq 1 200)
do
if [ $i -lt 10 ]
then
sufijo=000$i.jpg
elif [ $i -lt 100 ]
then
sufijo=00$i.jpg
else
sufijo=0$i.jpg
fi
if [ $i -lt 56 ]
then
convert machete$sufijo -gravity South -font Luxi-Sans-Bold -pointsize 50 -fill White -stroke Black -strokewidth 3 -annotate +0+0 "MACHETE NO MANDA MENSAJES" fotograma$sufijo
else
convert machete$sufijo -gravity South -font Luxi-Sans-Bold -pointsize 70 -fill White -stroke Black -strokewidth 3 -annotate +0+0 "MACHETE IMPROVISA" fotograma$sufijo
fi
done
En este caso, la mayoría de los fotogramas son iguales o muy parecidos, así que voy a borrar unos cuantos. Al contrario que con ffmpeg, a la hora de hacer imágenes animadas con ImageMagick la numeración puede contener saltos.
Y además, tenemos la posibilidad de optimizar las imágenes para que el fichero resultante pese menos con -layers Optimize, que podemos usarlo así:
convert fotograma0* -delay 5 -loop 0 -layers Optimize macheteimprovisa.gif
Podéis ver el resltado en Twitter:
https://twitter.com/hacemoswebserie/status/1038551976131350528
Ya hemos visto cómo unir imágenes con -delay para crear un gif animado. Pero -delay, que es muy sencillo de usar, no permite definir cuántas veces queremos que se repita el bucle ni la velocidad a la que queremos que se muestren las imágenes que forman la animación.
Para estas dos funcionalidades tenemos:
-loop que permite definir el número de veces que queremos que se repita una determinada animación. Le indicamos el número de veces que queremos que se repita. Y si queremos que se repita infinitas veces, se lo indicamos con 0.
-delay que establece la velocidad a la que se mostararán las imágenes en centésimas de segundo. Es decir, si queremos que entre imagen e imagen pase un segundo, le indicaremos 100.
Así:
convert -delay 10 -loop 0 param* param.gif
Si quieren ver diversas fórmulas para crear imágenes que van mutando y luego unirlas en ficheros gif, pueden leer este hilo de Twitter:
https://twitter.com/hacemoswebserie/status/1037884393430429699