
Estoy intentando escribir un script (script1.sh) que encuentre todas las palabras posibles cuando se le presente un revoltijo de letras.
Las palabras deben comenzar con la primera letra del revoltijo y terminar con la última letra.
Las letras de la palabra deben seguir el orden de las letras en el revoltijo.
Cada letra del revoltijo se puede utilizar más de una vez.
Así que esto
./script1.sh "qwertyuytresdftyuiokn"
debería salir queen
pero question
no "silenciarse" porque "e" viene antes que "u" e "i" en el revoltijo.
Intenté asignar la primera, la última y las letras restantes a variables, luego usé egrep para encontrar las palabras, pero no pude encontrar una manera de usar el orden de las letras. Entonces este también me da palabras inválidas.
#!/bin/bash
first_letter=$(echo $@ | cut -c1)
last_letter=$(echo $@ |rev| cut -c1)
remaining_letters=$(echo $@ | cut -c2- | rev | cut -c2-)
grep -E "^$first_letter[$remaining_letters]*$last_letter$" /usr/share/dict/words
Luego intenté convertir el revoltijo en una matriz, pero nuevamente no pude encontrar la manera de encontrar palabras que obedecieran el orden en el revoltijo.
Respuesta1
#!/bin/sh
pttrn="^$(printf '%s' "$1" | sed -e 's/\(.\)/\1*/g' -e 's/\*/\\+/' -e 's/\*$/\\+/')"'$'
grep "$pttrn" /usr/share/dict/words
Se obtiene un patrón a partir del primer argumento inyectando *
después de cada carácter. Luego el primero *
se cambia a \+
; también lo es el último *
. Además ^
y $
se agregan. Su entrada de ejemplo genera el siguiente patrón:
^q\+w*e*r*t*y*u*y*t*r*e*s*d*f*t*y*u*i*o*k*n\+$
Este patrón es el patrón correcto para grep
. q
debe aparecer al menos una vez al principio, n
debe aparecer al menos una vez al final. Cada letra del medio puede aparecer cero o más veces, el orden se mantiene.
Tenga en cuenta que el guión es tonto. Si proporciona información con , .
o algo así, obtendrá una expresión regular más allá de la especificación. Proporcione información sensata o expanda el script para validarlo.[
]
Ejemplos:
$ ./script1.sh qwertyuytresdftyuiokn
queen
question
$ ./script1.sh te
tee
$ ./script1.sh superuser
seer
serer
spur
super
supper
surer
$
Respuesta2
He aquí una forma de abordarlo
Primero, filtre la lista de palabras solo para aquellas palabras que comienzan y terminan con las mismas letras que el revoltijo. Por ejemplo, si el revoltijo se pasa como parámetro posicional (y suponiendo un shell $1
reciente )bash
grep -x "${1:0:1}.*${1:(-1):1}" /usr/share/dict/words
Luego, toma cada una de estas palabras y desmenúzalas en una expresión regular. No se me ocurre una manera "agradable" de hacerlo, pero con GNU sed podrías hacerlo, por ejemplo.
$ sed -E 's/(.)\1*/+.*\1/2g' <<< "queen"
q+.*u+.*e+.*n
Ahora pruebe el revoltijo con cada patrón generado.
Poniendolo todo junto:
$ cat script1
#!/bin/bash
wordlist=/usr/share/dict/words
while IFS= read -r word; do
grep -qEx "$(sed -E 's/(.)\1*/+.*\1/2g' <<< "$word")" <<< "$1" && printf '%s\n' "$word"
done < <(grep -x "${1:0:1}.*${1:(-1):1}" "$wordlist")
entonces
$ ./script1 qwertyuytresdftyuiokn
queen
question
Respuesta3
Aquí hay otro (ejecutado en bash
). El python
código genera la expresión regular y se la envía grep
. grep
luego trabaja con la salida de la venerable look
utilidad, que realiza una búsqueda binaria para recuperar todas las /usr/share/dict/words
palabras que comienzan con q
en el ejemplo. grep
por lo tanto, tiene un conjunto muy reducido de palabras para buscar
python3 -c 'import sys
arr = list(sys.argv[1])
print(*arr, sep="*")
' $1 | grep -x -f - <(look ${1:0:1})
Alternativamente, una solución look
+ python3
que evita expresiones regulares.
look q | ./finder.py "qwertyuytresdftyuiokn"
donde finder.py
es el siguiente:
#!/usr/bin/env python3
import sys
from itertools import groupby
seek_word = sys.argv[1]
for word in sys.stdin:
orig_word = word.strip()
word = ''.join(k for k, g in groupby(orig_word))
s_w = iter(seek_word)
i_word = iter(word)
if all(c in s_w for c in i_word) and not next(s_w, None):
print(orig_word)