А регулярными выражениями вообще можно проверить такое?

slego

Новичок
А регулярными выражениями вообще можно проверить такое?

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

1. Состоит из букв, цифр.
2. Одни и те же символы не могут встречаться подряд много раз.

Например, выражения, которые являются валидными в моем случае:
PHP:
asdf5dhe78ejs7
74hj9dkdje78
hjd8739k
Невалидные:
PHP:
aaakkklllsss
555s6skk88
kdlskf999
11kxsff
Т.е. там, где происходит задвоение, утроение и т.д. символов - это плохие выражения.

Как проверить диапазон символов по всей длине строки, вроде понятно
PHP:
/^[a-zA-Z\d]*$/
Непонятно, куда тут вставить что-то вроде
PHP:
^[a-z]{2,}^[A-Z]{2,}^[\d]{2,}
(читай все, кроме маленьких букв подряд более одного раза, кроме больших букв подряд более одного раза, кроме цифр подряд более одного раза).
Понимаю, записано безграмотно. Просто не понятно КАК можно проверить на вхождения каких-либо _подстрок_неопределенной_длины....

Или регулярками тут не обойтись?
 

Фанат

oncle terrible
Команда форума
самая распространённая проблема любителей регулярных выражений состоит в том, что они всегда обязательно хотят проверить всю строку на соответствие всем разрешённым символам.
при том, что почти всегда гораздо проще - найти хотя бы один неразрешённый.
 

WP

^_^
~^[a-z\d]*$~i - проверяем на формат.
~(.)\1~ - ловит задвоение
~(.)\1\1~ - ловит затроение.
 

slego

Новичок
"почти"...

Хорошо, возможно, привел несколько абстрактный пример.
Я не знаю КАК можно разделить здесь на конкретно разрешенные и конкретно запрещенные варианты.
Итак, конкретная задача. Строка поиска:

1. должны входить a-zA-Z, \d, %, _, *
2. должен стоять запрет на удвоенные **, утроенные *** и т.д. символы звезды.

Вариант с несколькими регулярками и обработкой строки типа замены всех *****...***, на * - хотелось бы обойти, в силу специфики приложения.
Просто еще раз повторюсь, что не нашел возможности в регулярке _просто_ описать все, кроме вхождения подстроки из определенных симвлов.
Ну хорошо, допустим проверяем: все, кроме строки из двух звезд
эээ.....
PHP:
   [^*]{2,}

но это означает: строка из любых двух символов кроме звезды.
Например, 3*, уже не прокатит... что-то туплю...

-~{}~ 28.07.06 12:19:

там после ^ и перед * должен стоять \ (в тексте форума комбинация \* в [] не выводится почему-то)
 

uliss

Новичок
PHP:
$pattern = "/[*]{2,}/";

if(preg_match($pattern, $subject)){
    echo "Invalid";
}
else {
    echo "OK!";
}
 

slego

Новичок
Автор оригинала: uliss
PHP:
$pattern = "/[*]{2,}/";

if(preg_match($pattern, $subject)){
    echo "Invalid";
}
else {
    echo "OK!";
}
Да, спасибо. Так делал. Но:
1. Именно эта ситуация (многократное повторение звезды подряд) проверяется еще проще substr_count("**"), каким-нибудь.
2. Мечтал о возможности проверить все условия в одном регэкспе :)
 

uliss

Новичок
Регулярка может быть любой другой - если изменятся условия и substr_count
тогда не поможет: /[a-z]{2,}/

2. А что, от этого так производительность страдает?

3. В крайнем случае можно обходить строку в цикле
PHP:
$subject = "a876hjqdd";
$length = strlen($subject);
$char = '';
for($i=0;$i<$length;$i++){
    if($char == $subject[$i])
        echo "Error!";
    $char = $subject[$i];
}
 

Фанат

oncle terrible
Команда форума
slego
1. Именно эта ситуация (многократное повторение звезды подряд) проверяется еще проще substr_count("**"), каким-нибудь.
не понял
в чём смысл этой глубокой мысли?
2. Мечтал о возможности проверить все условия в одном регэкспе
не понял.
а разве в итоге получился не один регэксп?

-~{}~ 30.07.06 21:13:

uliss
ты считаешь, что отдельный обход в цикле резко повысит производительность?

-~{}~ 30.07.06 21:19:

uliss
PHP:
$pattern = "/[*]{2,}/";

if(preg_match($pattern, $subject)){
    echo "Invalid";
}
else {
    echo "OK!";
}
и долго ты думал над этим кодом?

slego
Да, спасибо. Так делал.
ты действительно так и сделал?
а что оно не работает - это тебя не смущает?
 

uliss

Новичок
Фанат
Цикл даже может снизить производительность - если автору вопроса так важно - пусть проводит профилирование. Я просто паказал ему вариант решения.

Над кодом думал недолго :)
Код:
gentoo mysql # php -r '
> $subject = "fdky329or*&cmk**ds,m";
> $pattern = "/[*]{2,}/";
>
> if(preg_match($pattern, $subject)){
>     echo "Invalid";
> }
> else {
>     echo "OK!";
> }
> '
Invalidgentoo mysql #
Ну и где оно не работает?
 

Gorynych

Посетитель PHP-Клуба
uliss а самми-то понял, что написали?

подсказываю - Ваш рег.эксп реагирует на удвоение "*".

если хотите запустите код:
Код:
$arr = array(
"asdf5dhe78ejs7",
"74hj9dkdje78",
"hjd8739k",
"aaa**kkklllsss",
"555s6skk88",
"kdlskf999",
"11kxsff"
);

$pattern = "/[*]{2,}/";
foreach($arr as $subject) {
    if(preg_match($pattern, $subject)){
        echo "$subject - Invalid\n";
    } else {
        echo "$subject - OK!\n";
    }
}
но вообще путанница в голове налицо :-(
 

uliss

Новичок
Читайте топик внимательнее:
Итак, конкретная задача. Строка поиска:

1. должны входить a-zA-Z, \d, %, _, *
2. должен стоять запрет на удвоенные **, утроенные *** и т.д. символы звезды.
 

slego

Новичок
Автор оригинала: Фанат
slego
ты действительно так и сделал?
а что оно не работает - это тебя не смущает?
Эээ.. А что ИМЕННО не работает?
PHP:
$value = "ssd2345lkj";
echo $value.": ".(preg_match("/[*]{2,}/", $value) ? "ok" : "failed")."<br/>";    // failed

$value = "ssd2345l**kj";
echo $value.": ".(preg_match("/[*]{2,}/", $value) ? "ok" : "failed")."<br/>";    // ok

$value = "ssd2345l*kj";
echo $value.": ".(preg_match("/[*]{2,}/", $value) ? "ok" : "failed")."<br/>";    // failed

$value = "ss*d2*345lkj";
echo $value.": ".(preg_match("/[*]{2,}/", $value) ? "ok" : "failed")."<br/>";    // failed

$value = "ssd2***345lkj";
echo $value.": ".(preg_match("/[*]{2,}/", $value) ? "ok" : "failed")."<br/>";    //  ок
Вроде как проверка на вхождения подстрок типа "**", "***", ... проверяется корректно.

Автор оригинала: Фанат
не понял.
а разве в итоге получился не один регэксп?
Я же вроде как "уточнил" задачу :)
1. Одним нужно проверять допустимый набор симоволов.
2. Другим вхождение подстрок, состоящих из одного и того же символа и длиной более одного символа (в данном конкретном случае - это звезда).

Автор оригинала: Фанат
не понял
в чём смысл этой глубокой мысли?
Вот именно второе условие можно проверить, используя строковые функции. Например, substr_count("**"), т. е. лишний раз не трогать регэкспы.

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

Фанат

oncle terrible
Команда форума
Ну, если проверять надо именно повторение звезды, то работает.
Только это противоречит первоначальной задаче, а менять условия на ходу - это проявлять неуважение к форуму.

И, самое интересное - какой в этом смысл? Какая практическая задача заставляет тебя искать только повторение звёзд?
 

slego

Новичок
Хм...А кто принципиально меняет задание?
Сначала была общая постановка. Потом, упростил немного, разбил на подзадачи. Что я поменял?

Смысл простой - строка запроса. Вводить можно буквы, цифры, знак подчеркивания, знак процента. Знак звезды используется как маска.
Т.е. авто* , *ботин*, *авто*бот*.

Далее произвожу замену * на % - и, после всех обработок строки (экранирование опасных символов, оборачивание в кавычки и т.д.), подставляю в запрос.

Проблемы начинается, когда вводят что-то типа авто**бот*.
Пока просто заменяю все удвоенные, утроенные и т.д. подстроки звезды на одинарный символ %.

Но, самое нехорошее, если введут просто что-нибудь ******
Тогда, в результате получается LIKE из одного символа %.... а запросы очень тяжелые.

Еще в догонку о "менять условия на ходу" - ты же сам сказал о проблеме всех любителей регэкспов:
самая распространённая проблема любителей регулярных выражений состоит в том, что они всегда обязательно хотят проверить всю строку на соответствие всем разрешённым символам.
при том, что почти всегда гораздо проще - найти хотя бы один неразрешённый.
Вот я для простоты и поменял на обратное условие. Ищем не все, кроме удвоенной звезды, а ищем просто удвоенную звезду...
 

Фанат

oncle terrible
Команда форума
Вот я для простоты и поменял на обратное условие.
условие "искать удвоенные звёзды" не обратно условию искать любые двоенные символы.

а с остальным всё ясно.


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

whirlwind

TDD infected, paranoid
slego стоило такую канитель разводить, вместо того, что бы сразу объяснить что тебе надо

PHP:
echo preg_replace('/\*+/','%',"авто**бот*");
 

slego

Новичок
whirlwind
а ты почитай ВЕСЬ топик, а не последнюю мою фразу.
Обрати внимание на форму глагола
Пока просто >>>заменяю<<< все удвоенные, утроенные и т.д. подстроки звезды на одинарный символ %.
Т.е., это я _уже_ делаю. Проблема не в замене, а в нахождении.


Автор оригинала: Фанат
условие "искать удвоенные звёзды" не обратно условию искать любые двоенные символы.
Игра слов. Не пойму, к чему придирания, правда :confused: . Cначало было - _любые_ символы. Потом, чтобы конкретизировать, для простоты остановился на одном определенном символе. От простого - к сложному.

Автор оригинала: Фанат
ну и чего ты не воспользовался? или тебе неизвестен оператор "или" в регулярных?
Хм... А не воспользовался от того, что выражение должно звучать так

[все буквы, цифры, знак звезды] | [НЕ удвоенный знак звезды]

Понятно как записать первую скобку. Понятно как записать [удвоенный знак звезды].

Не понятно как написать такое
PHP:
$value = "ssd234**5lkj";
echo $value.": ".(preg_match("/[a-z\d*]*|^[*]{2,}/", $value) ? "ok" : "failed")."<br/>";  // ok
чтобы оно выдавало failed :(

-~{}~ 31.07.06 12:24:

Хотя, пожалуй, не так.. Как раз нужно

[все буквы, цифры, знак звезды] AND [НЕ удвоенный знак звезды]
 
Сверху