linux - tutorial - web applications with django




Filtro Grep del diccionario (4)

Me está costando aprender a usar grep para una clase en la que estoy esperando que alguien pueda ayudarme a guiarme en esta tarea. La tarea es la siguiente.

Usando grep, imprima las 5 letras minúsculas del diccionario de Linux que tienen una sola letra duplicada una vez (aabbe o ababe no son válidas porque tanto a como b están en la palabra dos veces). Al lado de esa impresión, la carta duplicada sigue comprando las letras no duplicadas en orden alfabético ascendente.

El Profesor notó que necesitaremos usar varias (6) instrucciones grep (conectando los resultados a la siguiente grep) y una declaración sed (String Editor) para reformatear el conjunto final de palabras, y luego colocarlas en un bucle de lectura donde rasgas separa las tres letras que no son dobles y clasifícalas.

Sample Output:
aback a bck 
abaft a bft 
abase a bes 
abash a bhs 
abask a bks 
abate a bet 

No he descubierto cómo hacer más que imprimir palabras de 5 caracteres,

grep "^.....$" /usr/share/dict/words |

El siguiente paso debería ser encontrar las palabras de 5 letras que contengan una letra duplicada. Para hacer eso, necesitarás usar referencias retrospectivas. Ejemplo:

grep "[az]*\([az]\)[az]*\$1[az]*"

El $1 recoge los contenidos del primer grupo entre paréntesis y espera unir ese grupo nuevamente. En este caso, coincide con una sola letra. Consulte: http://www.thegeekstuff.com/2011/01/advanced-regular-expressions-in-grep-command-with-10-examples--part-ii/ para obtener más descripciones de esta capacidad.

A continuación, deberá filtrar aquellos casos que tengan una letra repetida 3 veces o una palabra con 2 letras repetidas. Tendrá que usar el mismo truco de referencia posterior, pero puede usar grep -v para filtrar los resultados.

sed se puede usar para la visualización final. Grep simplemente te permitirá construir las líneas correctas a considerar.


La primera parte, obviamente, es usar grep para obtener solo las palabras que tienen una sola duplicación. Le daré algunas pistas sobre cómo hacerlo.

La clave es usar referencias retrospectivas , que le permiten especificar que algo que coincidió con una expresión anterior debería aparecer nuevamente. Entonces, si escribes

grep -E "^(.)...\1...\1$"

luego obtendrás todas las palabras que tienen la letra inicial reapareciendo en las posiciones quinta y novena. El punto de los corchetes es permitirle referirse más tarde a lo que corresponda entre corchetes; lo haces con un \1 (para que coincida con la cosa en el primer lote de corchetes).

Desea decir que debe haber un duplicado en cualquier parte de la palabra, lo cual es un poco más complicado, pero no mucho. Desea un carácter entre corchetes, luego cualquier número de caracteres, luego el carácter repetido (sin ^ o $ especificado).

Eso también incluirá aquellos donde hay dos o más duplicados, por lo que la siguiente etapa es filtrarlos. Puedes hacerlo mediante una invocación grep -v . Una vez que tenga su lista de palabras de 5 caracteres que tienen al menos un duplicado, páselos a través de una llamada grep -v que elimine cualquier cosa con dos (o más) duplicados. Eso tendrá un (.) Y otro (.) , y un \1 y un \2 , y estos pueden aparecer en varios órdenes diferentes.

También deberá quitar todo lo que tenga un (.) Y un \1 y otro \1 , ya que tendrá una letra con tres apariciones.

Eso debería ser suficiente para empezar, en cualquier caso.


Todo en un sed

sed -n '
# filter 5 letter word
/[a-zA-Z]\{5\}/ {

# lower letters
      y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxya/

# filter non single double letter
      /\(.\).*\1/ !b
      /\(.\).*\(.\).*\1.*\1/ b
      /\(.\).*\(.\).*\1.*\2/ b
      /\(.\).*\(.\).*\2.*\1/ b

# extract peer and single
      s/\(.\)*\(.\)\(.*\)\2\(.*\)/a & \2:\1\3\4/
# sort singles
:sort
      s/:\([^a]*\)a\(.*\)$/:\1\2a/
      y/abcdefghijklmnopqrstuvwxyz/zabcdefghijklmnopqrstuvwxy/
      /^a/ !b sort

# clean and print
      s/..//
      s/:/ /p
      }' YourFile

posix sed so --posix en GNU sed


Tenga en cuenta que el diccionario contiene letras mayúsculas y también caracteres que no son letras, además de los caracteres extraños utilizados en el sur de Europa. decir "è".

Si desea distinguir "A" y "a", es automático, en cambio si "A" y "a" son la misma letra, en TODAS las invocaciones grep , debe usar la opción -i para indicar a grep que ignore caso.

Luego, siempre quiere pasar la opción -E , para evitar la llamada " backslashitis gravis" en la expresión regular que desea pasar a grep .

Además, si desea excluir las líneas que coinciden con una expresión regular de la salida, la opción correcta es -v .

Eventualmente, si desea especificar muchas expresiones regulares diferentes para una sola invocación de grep , esta es la forma (solo un ejemplo por cierto)

grep -E -i -v -e 'regexp_1' -e 'regexp_2' ... -e 'regexp_n'

Los preliminares nos persiguen, sigamos adelante, usemos la respuesta de chiastic-security como referencia para entender los procedimientos

  1. Solo hay estas posibilidades para encontrar un duplicado en una cadena de 5 caracteres

    (.)\1
    (.).\1
    (.)..\1
    (.)...\1

    grep -E -i -e 'regexp_1' ...

  2. Ahora tiene todos los dobles, pero esto no excluye los triples, etc. que se identifican por los siguientes patrones ( Editar agregó un grupo de patrones de tripletas adicionales que coinciden)

    (.)\1\1
    (.).\1\1
    (.)\1.\1
    (.)..\1\1
    (.).\1.\1
    (.)\1\1\1
    (.).\1\1\1
    (.)\1\1\1\1\

    desea excluir estos patrones, entonces grep -E -i -v -e 'regexp_1' ...

  3. en su punto, tienes una lista de palabras con al menos un par del mismo personaje, y no triples, etc. y quieres soltar dobles dobles, estas son las expresiones regulares que coinciden con dobles dobles

    (.)(.)\1\2
    (.)(.)\2\1
    (.).(.)\1\2
    (.).(.)\2\1
    (.)(.).\1\2
    (.)(.).\2\1
    (.)(.)\1.\2
    (.)(.)\2.\1

    y desea excluir las líneas con estos patrones, por lo que su grep -E -i -v ...

Una última pista, para jugar con mi respuesta copie unos pocos cientos de líneas del diccionario en su directorio de trabajo, head -n 3000 /usr/share/dict/words | tail -n 300 > ./300words head -n 3000 /usr/share/dict/words | tail -n 300 > ./300words para que pueda entender realmente lo que está haciendo, evitando sentirse abrumado por el volumen de la salida.

Y sí, esta no es una respuesta completa, pero tal vez sea demasiado, ¿no?





grep