Saltar al contenido

¿Cómo uso grep para encontrar líneas en las que cualquier palabra aparece 3 veces?

Solución:

Usando la definición de palabra estándar,

  • GNU Grep, 3 o más ocurrencias de cualquier palabra.

    grep -E '(W|^)(w+)W(.*<2>){2}' file
    

  • GNU Grep, solo 3 ocurrencias de cualquier palabra.

    grep -E '(W|^)(w+)W(.*<2>){2}' file | grep -Ev '(W|^)(w+)W(.*<2>){3}'
    

  • POSIX Awk, solo 3 ocurrencias de cualquier palabra.

    awk -F '[^_[:alnum:]]+' '{           # Field separator is non-word sequences
        split("", cnt)                   # Delete array cnt
        for (i=1; i<=NF; i++) cnt[$i]++  # Count number of occurrences of each word
        for (i in cnt) {
            if (cnt[i]==3) {             # If a word appears exactly 3 times
                print                    # Print the line
                break
            }
        }
    }' file
    

    Para 3 o más ocurrencias, simplemente cambie == para >=.

    Equivalente de golf de una sola línea:

    awk -F '[^_[:alnum:]]+' '{split("",c);for(i=1;i<=NF;i++)c[$i]++;for(i in c)if(c[i]==3){print;next;}}' file
    

  • GNU Awk, solo 3 apariciones del palabra ab.

    gawk 'gsub(/<ab>/,"&")==3' file
    

    Para 3 o más ocurrencias, simplemente cambie == para >=.


Material de lectura

  • 2 es una referencia hacia atrás.
  • w W < > expresiones especiales en GNU Grep.
  • los [:alnum:] Clase de caracteres POSIX.

¿Como esto?

egrep '(<.+>).+<1>.+<1>'
  • egrep (o grep -E) habilita expresiones regulares extendidas, que son necesarios para referencias inversas
  • <.+> coincidirá con cualquier palabra de al menos 1 carácter

    • < resp > coincidir con los límites de las palabras (en su intento, no tuvo en cuenta los límites de las palabras)
    • .+ coincide con una secuencia de uno o más caracteres (en su intento usó .* que coincide con una secuencia de cero ¡o más personajes!)
  • utilice referencias inversas para comprobar si la secuencia coincidente se produce por segunda vez (1) y una tercera vez (1 de nuevo).
    • permitimos cualquier secuencia de uno o más caracteres (.+) entre las coincidencias, por lo que “foo bar foo dorbs foo godly” coincidirá (hay 3 apariciones de la palabra “foo”).
    • si solo desea hacer coincidir palabras adyacentes (por ejemplo, “foo foo foo”), use algo como [[:space:]]+ en lugar de.

Supongo que su pregunta significa que si alguna de las palabras en la línea existe al menos 3 veces, imprima la línea, de lo contrario, deséchela. yo usaría awk, para una solución más legible y personalizable:

awk -F '\W+' '{
    delete c; for (i=1;i<=NF;i++) if (length($i) && ++c[$i]==3) {print; next}
}' file

Es un ciclo para todos los campos, contando sus ocurrencias por línea. Si alguna palabra llega a 3 veces, imprimirá la línea, eliminará la matriz y pasará a la siguiente línea. También existe una prueba de la longitud del campo para evitar imprimir en los campos vacíos contados.

Aquí podemos personalizar fácilmente el significado de “palabra” agregando diferentes o muchos separadores de campo, usando -F (se admiten los BRE y ERE estándar). En lo anterior, los separadores de palabras son todos caracteres excepto _ y [:alnum:]: awk -F '\W+' o awk -F '[^_[:alnum:]]+', similar a hacer coincidir los contratos de palabra con grep.

Para un lenguaje humano, es posible que necesitemos diferentes condiciones de palabra, como todo, excepto las letras, como: awk -F '[^[:alpha:]]+' o excepto letras y dígitos: awk -F '[^[:alnum:]]+' o incluir no solo el guión bajo, sino también el guión en palabras: awk -F '[^-_[:alnum:]]+'.

Sin configurar -F, solo se utilizan los caracteres de espacio en blanco.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *