2010-07-14 4 views
0

мне нужно найти дополнение этого:в Perl, как найти подстроку, которая не соответствует шаблону

$_ = 'aaaaabaaabaaabacaaaa'; 

while(/([a][a][a][a])/gc){ 
    next if pos()%4 != 0; 
    my $b_pos = (pos()/4)-1; 
    print " aaaa at :$b_pos\n"; 
} 

То есть, набор из 4-х caracters, что не является «аааа».
Ниже не работает

$_ = 'aaaaabaaabaaabacaaaa'; 

while(/([^a][^a][^a][^a])/gc){ 
    my $b_pos = (pos()/4)-1; 
    print "not a at :$b_pos\n"; 
} 

Конечно, я могу это сделать

$_ = 'aaaaabaaabaaabacaaaa'; 

while(/(....)/gc){ 
    next if $1 eq 'aaaa'; 
    my $b_pos = (pos()/4)-1; 
    print "$1 a at :$b_pos\n"; 
} 

не более прямой путь?

Чтобы уточнить ожидаемый результат, мне нужно найти все 4-х буквенные сюиты, которые не являются «аааа», а также там.
1-й код выхода

aaaa at :0 
aaaa at :4 

второй код должен вывести

not aaaa at :1 
not aaaa at :2 
not aaaa at :3 

третий выходной код, это то, что я ищу

abaa at :1 
abaa at :2 
abac at :3 

Я понимаю, что не было достаточно ясным , пожалуйста, примите мои извинения.
То, что я пытаюсь добиться, это как деление строки на группы из 4 букв, получение значения и позиции групп, которые не соответствуют шаблону.

Мой третий код дает мне ожидаемый результат. В это время он читает строку 4 буквы и обрабатывает те, которые не являются «aaaa».
Я также узнал, что, несмотря на все ваши предложения, мой первый код не работает должным образом, он должен пропустить, если pos()% 4! = 0, что будет означать, что шаблон охватывает две группы из 4 Я исправил код.

Вопреки всем ожиданиям, от меня и других, следующих ничего не Ouput на всех

/[^a]{4}/ 

я, вероятно, следует придерживаться с моим 3-кодом.

+1

B tw, '[a] [a] [a] [a]' можно записать как 'aaaa' – Amarghosh

+0

Согласен, это для ясности – kaklon

+0

Я не понимаю, что вы подразумеваете под pos()/4-1 ... Разве вы не имеете в виду pos() - 4 ??! А что такое обратное? Вы действительно хотите, чтобы все позиции занимали следующие четыре символа, они не «аааа»? – njsf

ответ

1

EDIT: После того, как некоторые более бесполезные и думал, что я нашел правильное решение, я оставлю предыдущий ответ для справки ...

кажется/АААА (АААА?!) .... | (? ! аааа) ..../дс является дополнением/AAAA/для ваших целей:

$_ = 'aaaaabaaabaaabacaaaa'; 
while(/aaaa(?!aaaa)....|(?!aaaa)..../gc){ 
    my $b_pos = (pos()/4)-1; 
    print substr($_,$b_pos*4,4)." at :$b_pos\n"; 
} 

дает в результате:

abaa at :1 
abaa at :2 
abac at :3 

Предыдущего ответ

Отрицательные опережения не взаимодействуют с «блоком» итерацией, даже в вашем небольшом примере вводе:

use POSIX floor; 
$_ = 'aaaaabaaabaaabacaaaa'; 
while(/(?!aaaa)..../gc){ 
    my $b_pos = floor(pos()/4); 
    print " !aaaa at :$b_pos str:".substr($_,$b_pos*4,4); 
    print " c_pos:".(pos()-4)." str:".substr($_,(pos()-4),4)."\n"; 
} 

С выходом:

!aaaa at :1 str:abaa c_pos:2 str:aaab 
!aaaa at :2 str:abaa c_pos:6 str:aaab 
!aaaa at :3 str:abac c_pos:10 str:aaab 
!aaaa at :4 str:aaaa c_pos:14 str:acaa 

Это происходит потому, что предпросмотр будет оцениваться по характеру, а не в блоках 4. Это означает, что в случае aaaabaaa он будет проверять aaaa, затем aaab, который не будет смотреть на aaaa, таким образом, они будут потребляться, а не baaa, как хотелось бы ...

Однако разумное использование карты, Grep и раскола решить эту проблему:

my $c = 0; 
print "!aaaa at positions: ", 
     join ",", map { $$_[1] } 
        grep { $$_[0] !~ /aaaa/ } 
         map { [$_, $c++ ] } 
          grep /./, split /(.{4})/, $_; 
print "\n"; 

приводит:

!aaaa at positions: 1,2,3 

Пояснение:

  1. сплит /(.{4}) /, $ _ разделит входные данные на список блоков из 4 символов
  2. Однако использование r Захват egexp в split может привести к тому, что в списке появятся пустые блоки, поэтому мы исключим их с помощью grep /./
  3. Теперь мы создаем кортежи ввода плюс номер блока (при этом нам нужно $ c, инициализированное до 0 ...)
  4. Теперь мы фильтровать элементы, которые не соответствуют «AAAA»
  5. Теперь на карте, чтобы получить только номер блока ...

чтобы соответствовать вашему точно вывод:

my $c = 0; 
print "", 
    join "\n", 
     map { $$_[0]." at: ".$$_[1] } 
      grep { $$_[0] !~ /aaaa/ } 
       map { [$_, $c++ ] } 
        grep /./, split /(.{4})/, $_; 
print "\n"; 
4
/(?!aaaa)/ 

Это негативное опережение, который соответствует в первом положении, в котором шаблон aaaa не совпадает.

В качестве альтернативы,

/[^a]{4}/ 

будет соответствовать 4-х символов вместе, которые все не a.

+0

Это то, во что я начинал сначала, но ничто из этого не дает ожидаемого результата – kaklon

+0

Возможно, покажите нам, что вы на самом деле делаете? – Amber

+0

@kaklon это правильный ответ в соответствии с текущей формой вопроса - если это не то, что вы хотите, возможно, вам следует объяснить немного больше. Добавьте примерные строки с обеих сторон - что должно и не должно совпадать. – Amarghosh

0

Как об этом:

/[^a]{4}/ 
+0

Этот шаблон не является дополнением к '/ a {4} /' (например, он не соответствует '(a {3} b) +'). Извините за верховую езду на мертвой лошади ... – collapsar

+0

@collapsar: Это не просто мертвая лошадь, это окаменевшая окаменелость лошади, которую вы едете (даже ОП выяснил. Вы прочитали последнее предложение вопроса OP?). BTW: Вы также можете покататься на этой ископаемой в ответе Амберса. И: конечно, это не соответствует 'a {3} b) +'! Думаю, ты говоришь 'aaab' ;-) – Curd

0

Попробуйте это:

/(?:(?!aaaa)[a-z]){4}/g 

Перед каждого символа совпадают, предпросмотр гарантирует, что они не являются aaaa.

Смежные вопросы