texto - ¿Puede grep mostrar solo palabras que coincidan con el patrón de búsqueda?
ls grep (14)
ripgrep
Aquí están los ejemplos usando ripgrep
:
rg -o "(/w+)?th(/w+)?"
Coincidirá con todas las palabras que coincidan con th
.
¿Hay una manera de hacer que grep produzca "palabras" de archivos que coincidan con la expresión de búsqueda?
Si quiero encontrar todas las instancias de, digamos, "th" en varios archivos, puedo hacerlo:
grep "th" *
pero la salida será algo como (negrita es por mí);
some-text-file : the cat sat on the mat some-other-text-file : the quick brown fox yet-another-text-file : i hope this explains it thoroughly
Lo que quiero que produzca, usando la misma búsqueda, es:
the
the
the
this
thoroughly
¿Es esto posible usar grep? ¿O usar otra combinación de herramientas?
Es más simple de lo que piensas. Prueba esto:
egrep -wo ''th.[a-z]*'' filename.txt #### (Case Sensitive)
egrep -iwo ''th.[a-z]*'' filename.txt ### (Case Insensitive)
Dónde,
egrep: Grep will work with extended regular expression.
w : Matches only word/words instead of substring.
o : Display only matched pattern instead of whole line.
i : If u want to ignore case sensitivity.
No estaba satisfecho con la sintaxis de awk, pero me gustó la idea de usar una utilidad para hacer esto.
Parece que ack (o ack-grep si usas Ubuntu) puede hacer esto fácilmente:
# ack-grep -ho "/bth.*?/b" *
the
the
the
this
thoroughly
Si omites la marca -h obtienes:
# ack-grep -o "/bth.*?/b" *
some-other-text-file
1:the
some-text-file
1:the
the
yet-another-text-file
1:this
thoroughly
Como --output
adicional, puede usar el indicador de --output
para hacer búsquedas más complejas con la sintaxis más sencilla que he encontrado:
# echo "bug: 1, id: 5, time: 12/27/2010" > test-file
# ack-grep -ho "bug: (/d*), id: (/d*), time: (.*)" --output ''$1, $2, $3'' test-file
1, 5, 12/27/2010
Para buscar todas las palabras con "ícono-", el siguiente comando funciona perfectamente. Estoy usando Ack aquí, que es similar a grep pero con mejores opciones y buen formato.
ack -oh --type=html "/w*icon-/w*" | sort | uniq
Podrías canalizar tu salida grep a Perl de esta manera:
grep "th" * | perl -n -e''while(/(/w*th/w*)/g) {print "$1/n"}''
Prueba grep -o
grep -oh "/w*th/w*" *
Edición: coincidencia del comentario de Phil
De la documentación :
-h, --no-filename
Suppress the prefixing of file names on output. This is the default
when there is only one file (or only standard input) to search.
-o, --only-matching
Print only the matched (non-empty) parts of a matching line,
with each such part on a separate output line.
Puedes traducir espacios a nuevas líneas y luego grep, por ejemplo:
cat * | tr '' '' ''/n'' | grep th
Sólo awk
, no necesita combinación de herramientas.
# awk ''{for(i=1;i<=NF;i++){if($i~/^th/){print $i}}}'' file
the
the
the
this
thoroughly
También puedes probar pcregrep . También hay una opción -w
en grep , pero en algunos casos no funciona como se esperaba.
De Wikipedia :
cat fruitlist.txt
apple
apples
pineapple
apple-
apple-fruit
fruit-apple
grep -w apple fruitlist.txt
apple
apple-
apple-fruit
fruit-apple
Tuve un problema similar, buscando grep / pattern regex y el "patrón coincidente encontrado" como resultado.
Al final usé egrep (el mismo regex en grep -e o -G no me dio el mismo resultado de egrep) con la opción -o
Entonces, creo que podría ser algo similar a (no soy un maestro de expresiones regulares):
egrep -o "the*|this{1}|thoroughly{1}" filename
comando grep solo para coincidencias y perl
grep -o -P ''th.*? '' filename
Respuesta segura de distribución cruzada (¿incluyendo ventanas minGW?)
grep -h "[[:alpha:]]*th[[:alpha:]]*" ''filename'' | tr '' '' ''/n'' | grep -h "[[:alpha:]]*th[[:alpha:]]*"
Si usa versiones anteriores de grep (como 2.4.2) que no incluye la opción -o. Usa lo de arriba. De lo contrario, utilice el más simple para mantener la versión a continuación.
Respuesta segura de distribución cruzada de Linux
grep -oh "[[:alpha:]]*th[[:alpha:]]*" ''filename''
Para los resúmenes -oh
salida de las expresiones regulares coincide con el contenido del archivo (y no con su nombre de archivo), de la misma manera que espera que la expresión regular funcione en vim / etc ... La palabra o expresión regular que buscaría entonces es ¡Depende de usted! Mientras permanezca en POSIX y no en la sintaxis de Perl (consulte a continuación)
-o Print each match, but only the match, not the entire line.
-h Never print filename headers (i.e. filenames) with output lines.
-w The expression is searched for as a word (as if surrounded by
`[[:<:]]'' and `[[:>:]]'';
La razón por la cual la respuesta original no funciona para todos.
El uso de /w
varía de plataforma a plataforma, ya que es una sintaxis extendida de "perl". Como tal, la instalación de grep que está limitada para trabajar con clases de caracteres POSIX utiliza [[:alpha:]]
y no su perl equivalente de /w
. Ver la página de Wikipedia en la expresión regular para más
En última instancia, la respuesta POSIX anterior será mucho más confiable independientemente de la plataforma (siendo la original) para grep
En cuanto al soporte de grep sin la opción -o, el primer grep genera las líneas relevantes, el tr divide los espacios en nuevas líneas, el filtro grep final solo para las líneas respectivas.
(PD: Sé que la mayoría de las plataformas ya han sido parcheadas para / w ... pero siempre hay aquellas que se quedan atrás)
Crédito por la solución "-o" de la respuesta de @AdamRosenfield
$ grep -w
Extracto de la página del manual de grep:
-w: Seleccione solo las líneas que contienen coincidencias que forman palabras completas. La prueba es que la subcadena coincidente debe estar al principio de la línea o precedida por un carácter que no sea de palabra.
cat *-text-file | grep -Eio "th[a-z]+"