2011-01-07 16 views
5

rastgele yere Maç dizisi yalnızca n kere, örneğin atın:Regex soru: Ben bir normal ifade sorum var

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

Ben BZBZB eşleşen bir düzenli ifade için arıyorum sadece 012.n kez. Bir satırda
. Yani, diziyi sadece bir kez eşleştirmek isteseydim, sadece ilk satırı çıktı olarak almalıyım.

Dize, metinde rastgele yerlerde oluşur. Ve regex grep veya egrep ile uyumlu olmalıdır ...

Şimdiden teşekkürler. grep man sayfasından

cevap

8

grep '\(.*BZBZB\)\{5\}' 5 kez yapacaktır, ancak bu, grep'in bir çizginin herhangi bir alt dizesinin eşleşip eşleşmediğini kontrol ettiği için 5 kat veya daha fazla görünen her şeyle eşleşecektir. Grep'in normal ifadelerinde (yalnızca karakterlerde) dizelerle negatif eşleşmesi için herhangi bir yolu olmadığından, örneğin, dizede kullanılan karakterlerin eşleştirilmesinin mümkün olmadığını bilmedikçe, bu tek bir komutla gerçekleştirilemez. başka yerlerde kullanıldı.

Ancak, iki grep komutları yapabilirsiniz:

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

BZBZB tam 5 kez göründüğü çizgileri dönecektir. (Temelde, 5 veya daha fazla kez olumlu bir çek ve sonra altı veya daha fazla kez negatif çek yapıyor.)

1

:

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

birincisi önceki dizede "BZ" tüm örneklerini bulur:

-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. 

yüzden iki grep ifadelere ihtiyaç içeriği satırlara dahil etmeden. Her örnek kendi hattına tükürülür. İkincisi, her bir satırı tükürür ve n çizgileri bulunana kadar devam eder.

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

Umarım bu size ihtiyaç şeydir.

+0

Ben, ben bir çizgide diziyi n defa eşleşen oldu demek ne doğru soruyu formüle vermedi düşünüyorum üzgünüm. Her satır için satır başına – 3sdmx

+0

n kez? – mklauber

0

Onun çirkin ama grep önde iddialarını görünüyorum eğer, bu çalışması gerekir:

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

Düzenleme - Yukarıdaki {5}, OP'deki n times değişkenidir. GNU grep, -P seçeneğini kullanarak Perl gibi iddialar yapar gibi görünüyor.

Perl örnek

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"; 
} 

Çıktı

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

egrep, normal ifadeleri genişletmiştir, ancak eminim ki ileriye dönük iddiaları desteklemiyor. Ve eğer yaparsa, bu doğru sözdizimi değildir. Bu davranır! (ya da daha doğrusu, \! çünkü komut satırlarındaki! tek tırnakların içinde bile bir olay referansı olarak kabul edilir) "!" Yani !? sadece "!" ile eşleşir veya "". –

+0

Perl stiline ihtiyacınız var (> sürüm 5 Perl). GNU grep, grep -P '^ (((?! BZBZB).) * BZBZB) {5} ((?! BZBZB).) * $' 'İkili yineleme ile normal grep çalıştırmak utanç olurdu aynı dosyada. Bu regex düzgün çalışıyorsa, görmeniz gerekiyorsa, prova kodunu Perl'e gönderebilirim. – sln