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
(ogrep -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.
- permitimos cualquier secuencia de uno o más caracteres (
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.