 
			
				10.10.2016, 17:59
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Аспирант 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 08.03.2015 
					
					
					
						Сообщений: 78
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	| 
	
	
		
		
			
			 
				Почему не срабатывают условия в PHP?
			 
			
		
		
		
		Добрый день! 
Подскажите пожалуйста, почему не срабатывают условия?
 
Необходимо в тексте найти все буквы «a» 
    1. Если буква «a» стоит между двух букв «b» - вот так: «bab», то нужно заключить её в тег <b>, вот так: b<b>a</b>b; 
    2. Если буква «a» не стоит между двумя «b», то заключить её в тег <i> - вот так: <i>a</i>.
 
Это сильно-сильно упрощенная, необходимая мне конструкция, поэтому её необходимо сделать именно с помощью if-else.
 
Что делаю я:
 
// ищем в тексте, поочереди, все буквы «а»
if ( preg_match( "/a/miu", $text ) ) {
  // далее поверяем, находится ли буква «a», между двух букв «b»
  if ( preg_match( "/bab/miu", $text ) ) {
    // если условие верно, то заключаем её в тег <b>
    $text = preg_replace( "/bab/miu", "b<b>a</b>b", $text );
  // во всех остальных случаях...
  } else {
    // заключаем её в тег <i>
    $text = preg_replace( "/a/miu", "<i>a</i>", $text );
  }
}
Почему-то, срабатывает только первая часть условия, вот это:
 
// далее поверяем, находится ли буква «a», между двух букв «b»
  if ( preg_match( "/bab/miu", $text ) ) {
    // если условие верно, то заключаем её в тег <b>
    $content = preg_replace( "/bab/miu", "b<b>a</b>b", $text );
  }
А вторая часть никогда не срабатывает, вот эта:
 
else {
    // заключаем её в тег <i>
    $content = preg_replace( "/a/miu", "<i>a</i>", $text );
  }
Почему? И как заставить её работать?......  
		
	
		
		
		
		
		
		
	
		
			
			
	
			
			
			
			
			
				 
			
			
			
			
			
			
				
			
			
			
		 
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				10.10.2016, 18:23
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 14.01.2015 
					
					
					
						Сообщений: 12,989
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		
	
 
	| 
		
			Сообщение от snovapavel
			
		
	 | 
 
	| 
		Почему?
	 | 
 
	
 
 Потому, что неверно. Ваш первый пост о тегах также базировался на ошибочном представлении, а ведь надо было использовать preg_match_all, и так:
 
preg_match_all('/<(div)[^>]*>.*<p[^>]*>.+<\/p>.*<\/div>|<(blockquote)[^>]*>.*<p[^>]*>.+<\/p>.*<\/blockquote>/sU', $string, $matches, PREG_SET_ORDER);
foreach($matches as $r) {
    $r = current(array_diff(array_slice($r, 1), ['']));
    echo 'Параграф вложен в тег ' .$r . '</br>';
}
А в данном случае замена стразу без всяких проверок if...else
 
$text = preg_replace(['/bab/i', '/(?<!b>)a(?!<\/b)/i'], ['b<b>a</b>b', '<i>a</i>'], $text);
  
		
	
		
		
		
		
		
		
		
						  
				
				Последний раз редактировалось laimas, 10.10.2016 в 18:30.
				
				
			
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				10.10.2016, 19:15
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Аспирант 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 08.03.2015 
					
					
					
						Сообщений: 78
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	| 
	
	
		
		
		
		
		 Добрый день! 
 
Спасибо большое за ответ! 
 
Ваш совет: 
А в данном случае замена стразу без всяких проверок if...else... 
 
К сожалению, я не представляю, как написать ещё понятнее задачу... 
 
Смотрите: 
 
1. Ищем в тексте все буквы а и далее проверяем: 
____Если буква а стоит посредине букв б, то заключаем в тег <b>. 
____ВСЕ ОСТАЛЬНЫЕ буквы а (которые не стоят между двух букв б) в тег <i> 
 
Понимаете? И так уже целый день сегодня думал как максимально упростить. 
 
Я учу PHP. И мне бы лучше пока попроще... 
 
Если можете, помогите написать мою функцию. Буду очень признателен. 
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				10.10.2016, 19:46
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 14.01.2015 
					
					
					
						Сообщений: 12,989
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		
	
 
	| 
		
			Сообщение от snovapavel
			
		
	 | 
 
	| 
		Если можете, помогите написать мою функцию.
	 | 
 
	
 
 Нет у вас никакой функции, а что я написал, как раз делает то, что нужно, и если только буквы, то еще проще:
 
$text = 'abbb cccc ddbabddd fafdfff gggbabggg';
$text = preg_replace(['/bab/i', '/(?<!>)a(?!<)/i'], ['b<b>a</b>b', '<i>a</i>'], $text);
echo htmlspecialchars($text); //результат <i>a</i>bbb cccc ddb<b>a</b>bddd f<i>a</i>fdfff gggb<b>a</b>bggg
 
И паттерны передаются массивом и замена есть массив, как раз для того чтобы проще для понимания. Написать паттерн и сделать замену можно то ведь и иначе.
 
Если изучаете, то тогда с чего либо простого, начиная  отсюда - сначала сами выражения, а потом функции PCRE.  
		
	
		
		
		
		
		
		
		
						  
				
				Последний раз редактировалось laimas, 10.10.2016 в 19:54.
				
				
			
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				10.10.2016, 20:12
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Аспирант 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 08.03.2015 
					
					
					
						Сообщений: 78
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	| 
	
	
		
		
		
		
		 Спасибо вам большое за помощь. 
 
Если я вас правильно понял, то это условие работает так: 
 
preg_replace( // это понятно 
 
['/bab/i', // ищем любое регулярное выражение (в данном случае bab) 
 
'/(?<!>)a(?!<)/i'], // Простите, но вот это как расшифровывается? 
 
['b<b>a</b>b', // откуда вот это материализовалось?... непонимаю 
 
'<i>a</i>'], // это я так понял, означает в противном случае 
 
$text); // откуда что берём 
 
________________________________ 
 
А как добавить сюда третье условие? Скажем faf? 
 
Большое спасибо за помощь. 
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				10.10.2016, 20:24
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 14.01.2015 
					
					
					
						Сообщений: 12,989
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		
	
 
	| 
		
			Сообщение от snovapavel
			
		
	 | 
 
	| 
		Простите, но вот это как расшифровывается?
	 | 
 
	
 
 
	
 
	| 
		
			Сообщение от snovapavel
			
		
	 | 
 
	| 
		откуда вот это материализовалось?... непонимаю
	 | 
 
	
 
 Ну чтобы понимать, надо изучать.
 preg_replace может принимать аргументом паттерн и замену не только как строки, но и как массивы. 'b<b>a</b>b' - материализовалось из вашего условия  Если буква а стоит посредине букв б, то заключаем в тег <b>, хотя изначально речь шла о латинице, а посему модификатор u я просто опустил - латиница (en) и в utf будет тем же самым байтом. Если в паттерне указать "не запоминать" крайние по условию символы, то и замена была бы описана иначе.
 
(?<!>)a(?!<) - это означает что перед искомым символом не должно быть >, а после него не должно быть <. А вот почему так, они из чего материализуются, попробуйте ответить сами. А не получится ответить, тогда.... Но если чуток подумать, то вряд ли не будет найдет ответ. )
 
PS. Сперва с этим разберитесь, а потом уже  Скажем faf. ) Тем более, что в паттерне и заменах есть "мина". Я эту "свинью" подложил специально, ее надо обнаружить.  
		
	
		
		
		
		
		
		
		
						  
				
				Последний раз редактировалось laimas, 10.10.2016 в 20:52.
				
				
			
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				10.10.2016, 20:52
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Аспирант 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 08.03.2015 
					
					
					
						Сообщений: 78
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		Смотрите, конкретный пример, чтобы мне расставить теги <br> во всех пустых строках, кроме тех, которые находятся внутри тегов <pre> и <div>, мне надо писать так? 
$text = preg_replace(['/^\s*$/i', '/(?<!>)^\s*$(?!<)/i'], ['<br>', ''], $text);
 
И всё-таки, если бы к вам подошли и предложили, скажем, даже сумму 500 рублей и попросили дописать условие, именно через if else, это же можно сделать?
 
P. S. Оставим пока дискуссию что надо для парсинга текста использовать специальные скрипты и т. д., я пытаюсь, учить PHP в боевых условиях.
 
Ведь первая часть моих условий исполняется (когда мы определяем наличие соседних букв б)? Почему не исполняется часть «в противном случае»? Можете ответить? Или дописать именно её. Понимаете, я там хоть что-то понимаю.
 
Ещё раз спасибо за помощь.  
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				10.10.2016, 21:25
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 14.01.2015 
					
					
					
						Сообщений: 12,989
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		
	
 
	| 
		
			Сообщение от snovapavel
			
		
	 | 
 
	| 
		чтобы мне расставить теги <br> во всех пустых строках, кроме тех, которые находятся внутри тегов <pre> и <div>, мне надо писать так?
	 | 
 
	
 
 Конечно нет, это  не будет работать должным образом.
 
Чтобы работало так как вы пытались (опять таки, если пример о буквах), нужно получить искомый символ в его окружении - по одному символу слева и справа. Затем проходом в цикле найти в совпадении то, что интересует и принять соответствующее действие.
 
А вот если речь о тексте вне тегов, то нужно будет выделить такой текст и производить замену в нем, ибо, к примеру, сложно будет утверждениями определить пустую строку не принадлежащую тегу, так как для предшествующего текста в отрицательном утверждении подстроки должны быть одинаковой длины, что в реальном вашем коде конечно не будет соблюдаться.
 
Почитайте о preg_replace_callback().  
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				11.10.2016, 09:33
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Аспирант 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 08.03.2015 
					
					
					
						Сообщений: 78
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		laimas, 
Добрый день!
 
Спасибо вам за помощь.
 
Всё утро корпел над функцией, которую вы мне посоветовали. В результате написал следующий продуманный код, посмотрите, пожалуйста:
 
// берём контент
$content = preg_replace_callback(
  // поочерёдно перебираем в нём все пустые строки в их окружении
  // и каждую строку проверяем на соответствие и выполняем с ней то, или иное действие
  "/[\s\S]*(^\s*$)[\s\S]*/miu",
  function( $match_before ) {
    // смотрим, если пустая строка внутри pre (записываем результат в переменную $match_after)
    if ( preg_match( "/\<pre\>[\s\S]*(^\s*$)[\s\S]*\<\/pre\>/miu", $content, $match_after ) ) {
      // и выводим вместо неё надпись, что мы внутри
      $content = preg_replace( $match_after[1], "<p>Это строка внутри pre</p>", $content );
    // в противном случае, мы берём строку, которую нашли в самом начале
    // и так как она не подошла под первое условие
    // с чистой совестью выводим вместо неё сообщение, что мы НЕ внутри
    } else {
      $content = preg_replace( $match_before[1], "<p>Это строка НЕ внутри pre</p>", $content );
    }
  },
  $content
);
Ведь алгоритм написан верно?  
		
	
		
		
		
		
		
		
	
		
			
			
	
			
			
			
			
			
				 
			
			
			
			
			
			
				
			
			
			
		 
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				11.10.2016, 11:34
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 14.01.2015 
					
					
					
						Сообщений: 12,989
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		А запустить и проверить разве сложно? 
Во-первых второй аргумент функции у вас это анонимная функция и никакой $content в ней не будет доступно, а чтобы было доступно, нужно передать эту переменную в нее - function( $match_before ) use($content) { ... 
Во-вторых не изменение строки внутри функции, а для этого переменная должна передаваться в функцию по ссылке - function( $match_before ) use(&$content) { ..., а возвращать измененные фрагменты, иначе последствия непредсказуемы.
 
Запускайте свой код и вы как минимум получите ошибку. Вы что пишите, а проверять не проверяете?
 
В том, что вы нагородили в preg_replace_callback нет никакого смысла, да и вообще во всем коде.    
Что есть причина пустой строки, это двойное \r\n или \n. При этом непосредственно \r\n можно трактовать также пустой строкой. Что вы хотите получить вне тегов - заменить двойной перевод строки одиночным или сохранить оригинал?
 
$s = 'aaa
bbb
<div>ccc
ddd</div>
eee
<pre>fff
ggg</pre>';
$s = preg_replace_callback('/<div>.+<\/div>|<pre>.+<\/pre>/s', function($v) {
    return str_replace('<br />', '', $v[0]);
}, nl2br($s));
echo $s;
//затем вместо nl2br($s) пропишите так:
preg_replace('/^\s+$/m', '<br />', $s)
//и посмотрите на разницу
Примечание - preg_replace_callback для посмотреть, все это можно сделать и без нее.  
		
	
		
		
		
		
		
		
	
		
			
			
	
			
			
			
			
			
				 
			
			
			
			
			
			
				
			
			
			
		 
		
	
	
	 | 
 
 
	 
		 | 
 
 
 
 |  
  |