Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум Регулярные Выражения

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: поправьте регулярное выражение
 
 автор: sl1p   (28.01.2010 в 12:22)   письмо автору
 
 

#(?<=[\W])(?<!(<a[^>]*>)){$keyWord}(?=[\W])#i


ругается:
Warning:  preg_replace() [function.preg-replace]: Compilation failed: lookbehind assertion is not fixed length at offset 14


нужно сделать так, чтобы слева от слова, был не словестный символ и оно не находилось бы уже в теге <A>...

заранее спасибо!)

  Ответить  
 
 автор: heed   (28.01.2010 в 17:19)   письмо автору
 
   для: sl1p   (28.01.2010 в 12:22)
 

> (?<!(<a[^>]*>))

в "заглядывающих назад" подмасках нельзя использовать квантификаторы типа *+, только если какие-нибудь {3}

С такими непонятными сложными условиями как будто надо что-то типа
(<a\b[^>]*>)?(?(1)(?!)|(\b$keyWord\b))

(?!) делает совпадение ошибочным
(?(1)если|или) проверяет было-ли $1

но такое тоже работает медленно, чем например было-бы
"#<a\b[^>]*>\w+|(\b$keyWord\b)#"
т.к. при несовпадении в конце шаблона сравнение снова начинается с "начало"+1

  Ответить  
 
 автор: sl1p   (28.01.2010 в 18:53)   письмо автору
 
   для: heed   (28.01.2010 в 17:19)
 

Может вы тогда подскажете, возможно я не в правильную сторону думаю?

как заменить правильно эти выражения?
#квартир\w*#i
#квартир\w* посуточно#

тоесть чтобы не получилось в итоге:
<a href="http://localhost/apartments2" target="_blank" class="keyword"><a href="http://localhost/apartments" target="_blank" class="keyword">квартиры</a> посуточно</a>


зы. в обоих ваших примерах не учитывается условие если слово уже в ссылке и получается не нужное выше:)

  Ответить  
 
 автор: heed   (28.01.2010 в 20:02)   письмо автору
 
   для: sl1p   (28.01.2010 в 18:53)
 

не понял, чего у меня не получилось, там только (<a\b[^>]*>)?(?(1)(?!)|(\b$keyWord\b)) вроде должно было делать то что нужно , (только с другими номерами подмасок) но я ещё пока не тестил :)
если насчёт проверок (?<=\W)и(?=\W), то того-же самого можно просто \b , если в $keyWord по краям символы слов.

а это наверное одним выражением лучше
#квартир\w*(?:\s+посуточно)?#

  Ответить  
 
 автор: sl1p   (28.01.2010 в 20:29)   письмо автору
 
   для: heed   (28.01.2010 в 20:02)
 

#квартир\w*(?:\s+посуточно)?#
ну это никчему вроде :)
словосочетание задаётся точно, через форму пользователем как ключевое слово :)

а вот нащёт того что уже в теге, совсем х3..:(

  Ответить  
 
 автор: heed   (28.01.2010 в 21:06)   письмо автору
 
   для: sl1p   (28.01.2010 в 20:29)
 

насчёт тегов кажется понял, не нужно в тегах <a></a> парсить
, а насчёт ввода пользователем не понял.
Пользователю чего вообще должно быть можно вводить из символов, чтобы это безнаказанно попало в выражение ?
всмысле "два слова" "т р и слова " или вообще регулярные выражения?
и по html-файлу чего с найденными словами нужно сделать?

  Ответить  
 
 автор: sl1p   (28.01.2010 в 21:49)   письмо автору
 
   для: heed   (28.01.2010 в 21:06)
 

ну пользователю можно вводить только "\w+"
остальное убираю preg_quote и т.д.
символ % заменяю на \w*

а дальше идёт замена составленого выражения из слова на
<a href="#" class=\"keyword\">$0</a>

ну пользователь пока я:)) это для админки, поэтому ничего левого быть не может :)
для начала хотелось бы разобраться с самим выражением:)

  Ответить  
 
 автор: heed   (28.01.2010 в 22:32)   письмо автору
 
   для: sl1p   (28.01.2010 в 21:49)
 

всёравно не понял, если текст заменяется по просто тексту одним preg_replace()
, то чем не устраивает например простое выражение
<form action="" method="post">
<input type="text" name="re" value="с%"/>
<input type="submit" value="x"/>
</form><pre><?php
$txt 
'    
ну пользователю можно вводить только "\w+"
остальное убираю preg_quote и т.д.
символ % заменяю на \w*

а дальше идёт замена составленого выражения из слова
'
;

$re '';
echo (isset(
$_POST['re'])
    && (
$re =str_replace('%''\w*'preg_quotetrim($_POST['re']), '#'))))
    ? 
preg_replace('#\b'$re .'\b#i',  '<a href="#" class="keyword">$0</a>'$txt)
    : 
$txt;

echo 
"\n\n\n"'#\b'$re .'\b#i'
    
"\n\n\n"'#(<a\b[^>]*>)?(?(1)(?!)|\b'$re .'\b)#i';
только не учёл magic_quotes , и вообще думаю что нужно от пользовательского ввода оставить только \w и %

или ессли введено два слова идёт поиск каждого по очереди?

  Ответить  
 
 автор: sl1p   (29.01.2010 в 08:14)   письмо автору
 
   для: heed   (28.01.2010 в 22:32)
 

ну слова вводятся в текстареа и каждая новая строка = новое слово и в preg_replace суётся массив выражений. Так что такой вариант не прокатит 6)

  Ответить  
 
 автор: big-trot   (28.01.2010 в 22:45)   письмо автору
 
   для: sl1p   (28.01.2010 в 12:22)
 

Если я правильно понял самый первый вопрос


>нужно сделать так, чтобы слева от слова, был не словестный символ и оно не находилось бы уже в теге <A>...

предлагаю следующий вариант

#<a(?:(?!\b$keyWord\b)[^>])*>.*?(?<=[\W])($keyWord).*?</a>#i

  Ответить  
 
 автор: heed   (29.01.2010 в 12:05)   письмо автору
 
   для: sl1p   (28.01.2010 в 12:22)
 

тогда наверное только как-нибудь так
<form action="" method="post"> 
<textarea name="re">
    с%
    hr%      
    а%
</textarea> 
<input type="submit" value="x"/> 
</form><pre><?php 
$txt 
'     
ну пользователю можно вводить только "\w+" 
остальное убираю preg_quote и т.д.
href 
символ % заменяю на \w* 

а дальше идёт замена составленого выражения из слова 
'


function 
linker($m){
    return (
$m[0]{0} == '<') ? $m[0] : '<a href="#">'$m[0] .'</a>';
}

if(isset(
$_POST['re'])) {
$re split("[[:space:]]*\n[[:space:]]*"
    
str_replace('%''\w*'preg_quotetrim($_POST['re']), '#'))); 
print_r($re);
 foreach(
$re AS $k => $v) {
    if (
$v === '') {
        unset(
$re[$k]); break;
    }
    if (!
$k)    $re[$k] = '#\b'$v .'\b#i';
    else        
$re[$k] = '#<a\b[^>]*>[^<]*</a\s*>|\b'$v .'\b#i';
    echo 
"\n"htmlspecialchars($re[$k]);
 }
 if (
$re[0]) $txt preg_replace_callback($re'linker'$txt);

echo 
$txt;

вместо foreaach можно array_walk() какой-нибудь прикрутить

и с (<a\b[^>]*>)?(?(1)..... это работало только если сразу в <a> шло слово
, а чтобы какое-нибудь href не захавало похоже ещё сложнее чего-нибудь вставлять


//upd

хотя такой ещё вариант
<?php 
$txt 
'     
<a href="#">x - символ</a>
y - символ 
'


echo 
preg_replace('#\bсимв\w+\b(?!(?:(?!<a\b).[^<]*)*</a\b)#''<a href="#">$0</a>'$txt);

  Ответить  
 
 автор: sl1p   (29.01.2010 в 13:13)   письмо автору
 
   для: heed   (29.01.2010 в 12:05)
 

выражение: #<a\b[^>]*>[^<]*</a\s*>|\b'. $v .'\b#i
порадовало :)


но теперь получилась такая штука:
#квартир\w*#i 
#квартир\w* посуточно#


<a href="http://localhost/apartments" target="_blank" class="keyword">квартиры</a> <a href="http://localhost/apartments" target="_blank" class="keyword">КваРтира</a>
<a href="http://localhost/apartments" target="_blank" class="keyword"><a href="http://localhost/apartments2" target="_blank" class="keyword">квартиры посуточно</a></a>

  Ответить  
 
 автор: heed   (29.01.2010 в 13:19)   письмо автору
 
   для: sl1p   (29.01.2010 в 13:13)
 

>#квартир\w*#i
>#квартир\w* посуточно#

Так тут надо просто стазу определяться какие квартиры нужнее ,) посуточные или понесуточные :)
Если посуточные запосуточнить раньше чем непосуточные , то непосуточные понезапосуточнятся.

И там в массиве просто первое выражение урезанное.

//upd
и кажется split() вроде покушались с шестой версии php транклютировать , если я правильно понял что такое ereg-функции.

  Ответить  
 
 автор: sl1p   (29.01.2010 в 15:09)   письмо автору
 
   для: heed   (29.01.2010 в 13:19)
 

посуточные запосуточнить
таких слов не может быть :)если вы не например а про мой вариант.

могут быть "квартиры посуточно", "квартира посуточно" и оно должно быть важнее чем просто "квартир\w*"..

вот.

  Ответить  
 
 автор: heed   (29.01.2010 в 15:58)   письмо автору
 
   для: sl1p   (29.01.2010 в 15:09)
 

если нужно чтобы вводить можно было по разному, можно попробовать по длиннам строк уполрядочмвать
function lencmp($a, $b) 
{
    if (strlen($a) == strlen($b)) {
        return 0;
    }
    return (strlen($a) > strlen($b)) ? -1 : 1;
}

$arr = array('#кварт\w*#i', '#квартир\w*#i', '#квартир\w* посуточно#');
usort($arr, 'lencmp');
print_r($arr);

  Ответить  
 
 автор: sl1p   (29.01.2010 в 18:10)   письмо автору
 
   для: heed   (29.01.2010 в 15:58)
 

так а какая разница в каком порядке слова в массиве?)
всё равно ведь заменяет..

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования