¿Es la syntax grep diferente de la expresión regular?

Quiero extraer el nombre de los paquetes eliminados desde aquí “cat /var/log/dpkg.log | grep ‘remove'”

2013-09-09 15:57:34 remove activity-log-manager:i386 0.9.4-0ubuntu6.2  2013-09-09 15:57:35 remove activity-log-manager-control-center:i386 0.9.4-0ubuntu6.2  2013-09-09 15:57:38 remove alacarte:all 3.6.1-0ubuntu3  2013-09-09 15:57:41 remove deepin-software-center:all 2.1.2.1~precise~NoobsLab.com  

Quiero capturar solo el nombre de los paquetes entre eliminar y dos puntos después del nombre del paquete. No soy un experto en expresiones regulares, hice una expresión de expresiones regulares que parece hacer el trabajo pero cuando quiero aplicarlo con grep no pasa nada. Aquí está trabajando el patrón regex en evaluadores regex

 (?<=remove)(.*?)(?=:) 

Pero esto no está funcionando :

 cat /var/log/dpkg.log | grep 'remove' | grep '(?<=remove)(.*?)(?=:)' 

¿Que me estoy perdiendo aqui?

Hay un núcleo común de syntax de expresiones regulares, sin embargo, hay distintos sabores. Su expresión parece contener algunas características específicas del sabor de Perl, en particular el uso de aserciones complejas que describen el inicio y el final del patrón que debe coincidir, mientras que grep utiliza por defecto una syntax básica de expresión regular (BRE) que solo admite una más simple conjunto de estas coincidencias de longitud cero , como líneas- ( ^ , $ ) y anclajes de palabras ( \> , \< ).

Puede habilitar el soporte de expresiones regulares compatibles con perl (PCRE) en grep usando el interruptor de línea de comando -P (aunque tenga en cuenta que la página del manual actualmente lo describe como "experimental"). En su caso, es probable que también desee que el modificador -o imprima solo el patrón coincidente, en lugar de toda la línea, es decir,

 cat /var/log/dpkg.log | grep 'remove' | grep -oP '(?<=remove)(.*?)(?=:)' 

Tenga en cuenta que esta expresión puede fallar si se encuentra con paquetes que no tienen el sufijo: i386, ya que puede leer por adelantado los dos puntos correspondientes en la siguiente palabra, por ejemplo

 echo "2013-09-07 08:31:44 remove cifs-utils 2:5.1-1ubuntu2 " | grep -oP '(?<=remove)(.*?)(?=:)' cifs-utils 2 

Es posible que desee mirar awk en su lugar, por ejemplo,

 cat /var/log/dpkg.log | awk '$3 ~ /remove/ {sub(":.*", "", $4); print $4}' 

Además de BRE y PCRE, Gnu grep tiene un modo adicional denominado expresión regular extendida (ERE), especificado por el interruptor de línea de comando -E. La página del manual señala que

 In GNU grep, there is no difference in available functionality between basic and extended syntaxes. 

Sin embargo, debe tener en cuenta que "ninguna diferencia en la funcionalidad disponible" no significa que la syntax sea la misma. Por ejemplo, en BRE, el carácter + normalmente se trata como literal, y solo se convierte en un modificador que significa 'una o más instancias de la expresión regular precedente' si se escapa, es decir

 $ echo "123.456" | grep '[0-9]+\.[0-9]+' $ echo "123.456" | grep '[0-9]\+\.[0-9]\+' 123.456 

Mientras que para ERE es exactamente lo contrario

 $ echo "123.456" | grep -E '[0-9]+\.[0-9]+' 123.456 $ echo "123.456" | grep -E '[0-9]\+\.[0-9]\+' 

Una distinción similar se aplica para sed invocado sin y con el -r .

Desde la página del manual de grep :

grep busca los archivos de entrada con nombre (o entrada estándar si no se nombran archivos, o si se da un único guión-menos (-) como nombre de archivo) para las líneas que contienen una coincidencia con el PATTERN dado.

Que yo sepa, grep no tiene la capacidad de editar las líneas con las que concuerda; Yo usaría sed o posiblemente tr para eso. Cualquiera de los siguientes debe obtener lo que desea:

 cat /var/log/dpkg.log | grep 'remove' | sed 's/.*remove \([^:]*\):.*/\1/' cat /var/log/dpkg.log | grep 'remove' | sed -E 's/.*remove ([^:]*):.*/\1/' cat /var/log/dpkg.log | sed -n '/remove/s/.*remove \([^:]*:\).*/\1/p' cat /var/log/dpkg.log | sed -nE '/remove/s/.*remove ([^:]*):.*/\1/p' 

Honestamente, no estoy seguro de lo que está tratando de lograr tu (?<=remove)(.*?)(?=:) . En las expresiones regulares, los corchetes se usan para definir grupos de captura: puede ver que los he usado en los comandos sed aquí; allí, todo lo que coincida se reemplazará por el contenido del grupo de captura /1 , el primer grupo que será definido