Me gustaría encontrar líneas en archivos con la aparición de algún patrón y la ausencia de algún otro patrón. Por ejemplo, necesito encontrar todos los archivos / líneas, loom
excepto los que tienen gloom
. Entonces, puedo encontrar loom
con el comando:
grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp)
Ahora, quiero buscar loom
excluyendo gloom
. Sin embargo, los dos comandos siguientes fallaron:
grep -v 'gloom' -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp)
grep -n 'loom' -v 'gloom' ~/projects/**/trunk/src/**/*.@(h|cpp)
¿Qué debo hacer para lograr mi objetivo?
EDITAR 1: Me refiero a esoloom
ygloom
son las secuencias de caracteres (no necesariamente las palabras). Entonces, necesito, por ejemplo,bloomberg
en la salida del comando y no lo necesitoungloomy
.
EDICIÓN 2: Hay una muestra de mis expectativas. Las dos líneas siguientes están en la salida del comando:
Me enfrenté a los iconos que asomaban a través del velo de incienso.
Arty está llorando en un día sombrío .
Las dos líneas siguientes no están en la salida del comando:
Es lúgubre o terrible, grandes muckle doolders o 'cloods.
En la ronda suroeste de la sala heigh pyntit
there is a loom in the gloom
, ¿le gustaría que se imprimiera? Solo trato de entender si solo está buscando líneas donde se produce el telar de manera que no sea como parte de la penumbra o si realmente desea excluir las líneas que contienen la penumbra incluso cuando el telar aparece solo en otra parte de la línea. Publicar alguna entrada de muestra y salida esperada ayudaría.How do I find lines containing the string "loom" where "loom" is not preceded by the letter "g"
? Si hubiera publicado alguna entrada de muestra y la salida deseada, habría ayudado mucho. La respuesta a esa pregunta se incluye en las respuestas a continuación.loom
sin precedidog
. (Lo siento. Comencé a comentar ayer, pero nunca terminé. Este comentario fue enviado accidentalmente.)Respuestas:
¿Qué tal simplemente encadenar a los greps?
grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'
fuente
bloomberg
en la salida del comando y no lo necesitoungloomy
. Si una sola línea contuviera '... y Bloomberg no es sombrío sobre las perspectivas ...', eliminaría esa línea, pero es deseada (porque si contienebloomberg
).Otra solución sin encadenamiento
grep
:egrep '(^|[^g])loom' ~/projects/**/trunk/src/**/*.@(h|cpp)
Entre paréntesis, excluye el carácter
g
antes de cualquier aparición deloom
, a menos queloom
sean los primeros caracteres de la línea.fuente
Un poco viejo, pero bueno ...
La solución más votada de @houbysoft no funcionará ya que excluirá cualquier línea con "penumbra" en ella, incluso si tiene "loom". De acuerdo con las expectativas de OP, necesitamos incluir líneas con "telar", incluso si también tienen "penumbra" en ellas. Esta línea debe estar en la salida "Arty está haciendo un slooming en un día sombrío", pero esto será excluido por un grep encadenado como
grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'
En cambio, el ejemplo de expresión regular egrep de Bentoy13 funciona mejor
egrep '(^|[^g])loom' ~/projects/**/trunk/src/**/*.@(h|cpp)
ya que incluirá cualquier línea con "telar" en ella, independientemente de si tiene o no "penumbra". Por otro lado, si solo tiene pesimismo, no lo incluirá, que es precisamente el comportamiento que OP quiere.
fuente
Simplemente use awk, es mucho más simple que grep ya que le permite expresar claramente las condiciones compuestas.
Si desea omitir líneas que contienen ambos
loom
ygloom
:awk '/loom/ && !/gloom/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*.@(h|cpp)
o si quieres imprimirlos:
awk '/(^|[^g])loom/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*.@(h|cpp)
y si la realidad es que solo quieres líneas donde
loom
aparezca como una palabra por sí misma:awk '/\<loom\>/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*.@(h|cpp)
fuente
abc
ydef
yghi
en cualquier orden. Ahora compare eso conawk '/abc/ && /def/ && /ghi/'
. Ahora piense en cómoawk '/loom/ && !/gloom/'
se escribe el equivalente grep de en las respuestas de esta página.condition { action }
sintaxis de awks, pero luego es muy sencillo para cualquiera con cualquier experiencia en lenguaje C u otro lenguaje basado en Algol.grep -Hn --color
:awk '/loom/ && !/gloom/ { gsub(/loom/, color("1;31") "&" color(0)); print color(35) FILENAME color(36) ":" color(32) FNR color(36) ":" color(0) $0; }; function color(c) { return "\033[" c "m"; }'
-v
es la bandera de "coincidencia invertida", por lo que la canalización es una muy buena forma:grep "loom" ~/projects/**/trunk/src/**/*.@(h|cpp)| grep -v "gloom"
fuente
/ * ¿Podrías verte algo así?
grep -vn "gloom" `grep -l "loom" ~/projects/**/trunk/src/**/*.@(h|cpp)`
Los BACKQUOTES se utilizan como corchetes para los comandos, por lo que en este caso con
-l
habilitado, el código en BACKQUOTES le devolverá los nombres de los archivos, luego con -vn para hacer lo que quería: tener nombres de archivo, números de línea y también las líneas reales.ACTUALIZAR O con xargs
grep -l "loom" ~/projects/**/trunk/src/**/*.@(h|cpp) | xargs grep -vn "gloom"
Espero que ayude.*/
Por favor ignore lo que he escrito arriba, es una tontería.
grep -n "loom" `grep -l "loom" tt4.txt` | grep -v "gloom" #this part gets the filenames with "loom" #this part gets the lines with "loom" #this part gets the linenumber, #filename and actual line
fuente
Puede utilizar
grep -P
(perl regex) compatiblenegative lookbehind
:grep -P '(?<!g)loom\b' ~/projects/**/trunk/src/**/*.@(h|cpp)
Agregué
\b
para límites de palabras.fuente
\([^g]\|^\)
funciona. Y esto no excluye las líneas conloom
ygloom
.not gloom
.bloomberg
en la salida del comando y no lo necesitoungloomy
. Por tanto, los límites de las palabras son contraproducentes.grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'
fuente
bloomberg
en la salida del comando y no lo necesitoungloomy
. Si una sola línea contuviera '... y Bloomberg no es sombrío sobre las perspectivas ...', eliminaría esa línea, pero es deseada (porque si contienebloomberg
).¡Simplemente utilícelo!
grep -v
varias veces.Contenido del archivo
[root@server]# cat file 1 2 3 4 5
Excluir la línea o hacer coincidir
[root@server]# cat file |grep -v 3 1 2 4 5
Excluir la línea o hacer coincidir varios
[root@server]# cat file |grep -v 3 |grep -v 5 1 2 4
fuente
Pregunta: busque 'loom' excluyendo 'penumbra'.
Responder:
grep -w 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp)
fuente
bloomberg
en la salida del comando y no lo necesitoungloomy
. No creo que esa-w
sea la solución a ese enigma.