Вопрос по регулярному выражению: сопоставить последовательность только n раз на случайном месте - PullRequest
7 голосов
/ 08 января 2011

У меня есть вопрос регулярного выражения, например:

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

Я ищу регулярное выражение, соответствующее BZBZB только n раз.в линии.Так что, если я хочу сопоставить последовательность только один раз, я должен получить только первую строку в качестве вывода.Строка встречается в произвольных местах в тексте.И регулярное выражение должно быть совместимо с grep или egrep ...Заранее спасибо.

Ответы [ 3 ]

11 голосов
/ 08 января 2011

grep '\(.*BZBZB\)\{5\}' будет выполнено 5 раз, но это будет соответствовать всему, что появляется 5 или более раз, потому что grep проверяет, совпадает ли какая-либо подстрока строки.Поскольку у grep нет способа выполнить отрицательное сопоставление строк в своих регулярных выражениях (только символы), это нельзя сделать с помощью одной команды, если, например, вы не знаете, что символы, используемые в сопоставляемой строке, не являютсяиспользуется в другом месте.

Однако вы можете сделать это с помощью двух команд grep:

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

вернет строки, в которых BZBZB появляется ровно 5 раз.(В основном, это делает положительную проверку в течение 5 или более раз, а затем отрицательную проверку в течение шести или более раз.)

1 голос
/ 08 января 2011

Со страницы руководства 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.

Итак, нам нужны два выражения grep:

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

Первое находит все экземпляры "BZ"в предыдущей строке, без включения содержимого вокруг строк.Каждый экземпляр выкладывается на отдельной строке.Второй выводит каждую строчку и продолжается до тех пор, пока не будет найдено n строк.

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

Надеюсь, это то, что вам нужно.

0 голосов
/ 08 января 2011

Это ужасно, но если grep может смотреть вперед, это должно сработать:

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

Редактировать - {5} выше - это переменная n раз в OP.Похоже, GNU grep делает Perl как утверждения, используя опцию -P.

Пример 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";  
}  

Вывод

Found: 'this is BZBZB BZBZB BZBZB and 4 BZBZB then 5 BZBZB and done'
Found: 'BZBZBBZBZBBZBZBBZBZBBZBZB 1'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...