Что такое регулярное выражение Perl для поиска первого неповторяющегося символа в строке? - PullRequest
3 голосов
/ 31 марта 2010

Ваша задача, если вы решите принять ее, - написать регулярное выражение Perl, которое для данной строки будет возвращать первое вхождение символа, который не дублируется последовательно. Другими словами, оба предшествуют И, за ними следуют символы, отличные от самого себя (или соответственно начало / конец строки).

Пример:

IN: aabbcdecc
OUT: c

Обратите внимание, что «не дублируется последовательно» не означает «нигде в строке».

ПРИМЕЧАНИЕ: это должно быть чисто регулярное выражение. Например. решение, которое явно приходит на ум (клонировать строку, удалить все дубликаты и вывести первый оставшийся символ), не учитывается, хотя и решает проблему.

Вопрос вдохновлен моим несколько неуместным ответом на этот вопрос: Как найти первый неповторяющийся символ в строке, используя Perl?

Ответы [ 3 ]

2 голосов
/ 31 марта 2010
(?:(.)\1+)*(.?)

Получите 2-й захват. (Возвращает пустую строку, если каждый символ последовательно дублируется.)

Контрольные примеры:

~:2434$ perl -e "\"abc\" =~ m/(?:(.)\1+)*(.?)/; print \$2;"
a
~:2435$ perl -e "\"aabbcc\" =~ m/(?:(.)\1+)*(.?)/; print \$2;"

~:2436$ perl -e "\"aabbc\" =~ m/(?:(.)\1+)*(.?)/; print \$2;"
c
~:2437$ perl -e "\"aabcc\" =~ m/(?:(.)\1+)*(.?)/; print \$2;"
b
~:2438$ perl -e "\"aabcbbbcccccc\" =~ m/(?:(.)\1+)*(.?)/; print \$2;"
b
~:2439$ perl -e "\"aabbvbbcccccc\" =~ m/(?:(.)\1+)*(.?)/; print \$2;"
v
~:2440$ perl -e "\"aabbcdecc\" =~ m/(?:(.)\1+)*(.?)/; print \$2;"
c
~:2441$ perl -e "\"aabbccddeef\" =~ m/(?:(.)\1+)*(.?)/; print \$2;"
f
~:2442$ perl -e "\"faabbccddeef\" =~ m/(?:(.)\1+)*(.?)/; print \$2;"
f
~:2443$ perl -e "\"faabbccddeefax\" =~ m/(?:(.)\1+)*(.?)/; print \$2;"
f
~:2444$ perl -e "\"xfaabbccddeefx\" =~ m/(?:(.)\1+)*(.?)/; print \$2;"
x
~:2445$ perl -e "\"xabcdefghai\" =~ m/(?:(.)\1+)*(.?)/; print \$2;"
x
~:2446$ perl -e "\"cccdddeeea12345\" =~ m/(?:(.)\1+)*(.?)/; print \$2;"
a
~:2447$ perl -e "\"1234a5678a23\" =~ m/(?:(.)\1+)*(.?)/; print \$2;"
1

Или (не будет соответствовать, если каждый символ последовательно дублируется.)

(?:^|(.)(?!\1))(.)(?!\2)
1 голос
/ 31 марта 2010
use 5.010;
$str=~/^(([a-z])\g{-1}+)*(?<c>[a-z])/i;
$char = $+{c};
0 голосов
/ 31 марта 2010

Хотелось бы, чтобы у Perl был флаг отрицания регулярного выражения! т.е. вернуть все символы, которые НЕ соответствуют / регулярное выражение /

То, что вы ищете, действительно является дополнением захвата регулярных выражений:

m/(.)(\1)+/

Я перепробовал все предложения на этой странице со списком данных Брайана (результат в списке его программ). Ни одна работа не полностью.

Регулярное выражение:

(?:^|(.)(?!\1))(.)(?!\2) 

не соответствует началу 'f' в строках 2 и 3. Брайана не соответствует 'f' в начале строк 2 и 3 или любому из синглетонов в конце строки 5.

Регулярное выражение:

$str=~/^(([a-z])\g{-1}+)*(?<c>[a-z])/i;
$char = $+{c};

работает.

Единственное найденное мной регулярное выражение - это простое:

#!/usr/bin/perl
while( <DATA> ) {
    chomp;
    print "BEFORE: $_\n";
    s/(.)(\1)+//g;
    print "AFTER: $_\n";
    print "charater: " . substr($_,0,1) . "\n\n";
 }
__END__
aabbccddeef
faabbccddeef
faabbccddeefax
xfaabbccddeefx
xabcdefghai
cccdddeeea12345
1234a5678a23
aabbcdecc
abcdefg
aabbccddeef
cccdddeeea12345

Это работает в простом случае «дать первый символ». ((edit: reread: извините, я сейчас прочитал, что очевидное удаление двойников было не тем, что вы искали ...))

Рад слышать, если есть лучшее решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...