2011-01-07 9 views
5

Tengo una pregunta expresiones regulares, tomemos por ejemplo:pregunta Regex: Partido de secuencia n veces sólo en un lugar al azar

  1. ... AAA BZBZB CCCDDD ...
  2. ... BZBZB DDD BZBZB CCC ...

Busco a una expresión regular que coincide con BZBZB simplemente n veces.
en una línea. Entonces, si quisiera hacer coincidir la secuencia solo una vez, solo debería obtener la primera línea como salida.

La cadena se produce en lugares aleatorios en el texto. Y la expresión regular debe ser compatible con grep o egrep ...

Gracias de antemano.

Respuesta

8

grep '\(.*BZBZB\)\{5\}' hará 5 veces, pero esto coincidirá con cualquier cosa que aparezca 5 veces o más porque grep comprueba si alguna subcadena de una línea coincide. Debido a que grep no tiene forma de hacer coincidencias negativas de cadenas en sus expresiones regulares (solo caracteres), esto no se puede hacer con un solo comando a menos que, por ejemplo, usted sepa que los caracteres utilizados en la cadena que se va a combinar no utilizado en otro lugar.

Sin embargo, puede hacerlo de dos comandos grep:

cat temp.txt | grep '\(.*BZBZB\)\{5\}' | grep -v '\(.*BZBZB\)\{6\}'

volverá líneas en las que BZBZB aparece exactamente 5 veces. (Básicamente, se está haciendo una verificación positiva durante 5 o más veces y luego una comprobación negativa para seis o más veces.)

1

Según la página man grep:

-m NUM, --max-count=NUM 
    Stop reading a file after NUM matching lines. If the input is 
    standard input from a regular file, and NUM matching lines are 
    output, grep ensures that the standard input is positioned to 
    just after the last matching line before exiting, regardless of 
    the presence of trailing context lines. This enables a calling 
    process to resume a search. When grep stops after NUM matching 
    lines, it outputs any trailing context lines. When the -c or 
    --count option is also used, grep does not output a count 
    greater than NUM. When the -v or --invert-match option is also 
    used, grep stops after outputting NUM non-matching lines. 

Así que tenemos dos expresiones GREP:

grep -e "BZ" -o 
grep -e "BZ" -m n 

El primero busca todas las instancias de "BZ" en la cadena anterior, sin incluir el contenido alrededor de las líneas. Cada instancia se escupió en su propia línea. El segundo toma cada línea escupiendo y continúa hasta que se hayan encontrado n líneas.

>>>"ABZABZABX" |grep -e "BZ" -o | grep -e "BZ" -m 1 
BZ 

Espero que eso es lo que necesitabas.

+0

Lo siento, creo que no formuló la pregunta correctamente, lo que quiero decir estaba coinciden con la secuencia n veces en una línea. – 3sdmx

+0

n veces por línea para cada línea? – mklauber

0

su fea pero si el grep pueden hacer mirar hacia adelante afirmaciones, esto debería funcionar:

/^(((?!BZBZB).)*BZBZB){5}((?!BZBZB).)*$/

Editar - El {5} anterior es la variable n veces en el OP. Parece que GNU grep le gusta a Perl aserciones usando la opción -P.

muestra de Perl

use strict; 
use warnings; 

my @strary = ( 
    'this is BZBZB BZBZB BZBZB and 4 BZBZB then 5 BZBZB and done', 
    'BZBZBBZBZBBZBZBBZBZBBZBZBBZBZBBZBZBBZBZB BZBZB BZBZB', 
    'BZBZBBZBZBBZBZBBZBZBBZBZB 1', 
    'BZBZBZBBZBZBBZBZBBZBZBBZBZBBZBZB 2', 
); 

my @result = grep /^(((?!BZBZB).)*BZBZB){5}((?!BZBZB).)*$/, @strary; 

for (@result) { 
    print "Found: '$_'\n"; 
} 

salida

Found: 'this is BZBZB BZBZB BZBZB and 4 BZBZB then 5 BZBZB and done' 
Found: 'BZBZBBZBZBBZBZBBZBZBBZBZB 1' 
+0

egrep ha extendido expresiones regulares, pero estoy bastante seguro de que no admite las afirmaciones de mirar hacia adelante. Y si lo hace, esa no es la sintaxis correcta. ¡Se trata! (o más bien, \! ya que! en las líneas de comando se trata como una referencia de evento incluso dentro de comillas simples) como el carácter literal "!". Asi que !? solo coincide con "!" o "". –

+0

Necesita el estilo de Perl re (> versión 5 Perl). GNU grep sería 'grep -P '^ (((?! BZBZB).) * BZBZB) {5} ((?! BZBZB).) * $' 'Sería una pena ejecutar grep normal a través de una doble iteración en el mismo archivo. Esta expresión regular funciona correctamente. Puedo publicar un código de prueba en Perl si necesita verlo. – sln