Борьба с кавычками (с php)
spectator.ru представляет заметку, борющуюся за звание самой скучной заметки
года.
Поначитался я на разных сайтах про кавычки. Вот
тут, например, или вот
тут. Дескать, кавычки нужны только вот такие – « и вот такие – »,
а никак не такие – '', и все остальное – от лукавого!
Сел, стал думу думать, как бы так сделать, чтобы в тексте кавычки вот такие
– '' сами (с помощью маленького php-скрипта) заменялись на нужные «елочки».
Ясное дело – regular expressions, как же без них. Решил заодно и regular expressions
освоить, а то пока как-то не доводилось сталкиваться с ними очень близко... Проблемы
две: первая – чтобы кавычки чередовались правильно, открывающая кавычка – «,
а закрывающая – », и никак не наоборот; вторая – чтобы в html-тэгах они
даже и не думали меняться. Ни-ни.
В общем, думал я минут десять...
Желающие могут не читать дальше, а подумать сами, а потом сравнить полученный
результат с моим.
Думал я минут десять... Потом понял, что думаю не туда. На самом деле все гораздо
проще.
Первое. Ищем сначала открывающие кавычки. В нормальном тексте перед ними стоит
пробел. Всегда. Почти. В общем, – как правило. Если пробела нет, то текст просто
неграмотно набран, мы такие запущенные случаи рассматривать не будем. Итак,
$contents = str_replace (" \""," «", $contents);
// ищем в тексте проблел с кавычками и заменяем его на пробел с открывающейся
елочкой – «
Кроме пробела, открывающая кавычка может быть сразу после новой строки, верно?
Ищем и ее:
$contents = str_replace ("\n\"","«", $contents);
Таким образом html-тэги не попадают под этот поиск и замену, потому что
в них не бывает такого, чтобы перед кавычкой стоял пробел.
Есть еще случай, когда кавычка стоит после закрытия тэга, например <b>«Типа
текст»</b>. Ищем и этот случай:
$contents = str_replace (">\"",">«", $contents);
Итого имеем три строчки кода, которые ищут и заменяют открывающуюся кавычку:
$contents = str_replace (" \""," «", $contents);
$contents = str_replace ("\n\""," «", $contents);
$contents = str_replace (">\"",">«", $contents);
Почему str_replace, а не ereg_replace? Потому что эти три строчки со str_replace
в данном случае быстрей одной с ereg_replace в несколько раз. RTFM, как говорится.
А вот дальше без ereg_replace не обойтись.
Итак...
...начинаем искать с открывающейся кавычки («). Раз мы начинаем искать
с нее, html-тэги автоматически исключаются (смотри выше – почему) :
$contents = ereg_replace ('«
ищем последовательность символов (то есть [...]* ), в которую не входит
(то есть ^) вот такая – '' кавычка:
([^"]*)"'
И заменяем эту последовательность, то есть \\1 на эту последовательность в
кавычках: «\\1»:
,"«\\1»", $contents);
Для еще лучшей работы в конце стоит добавить еще и $contents = str_replace
("«","«", $contents);. Можно, конечно, делать это в первых трех
строчках, но у меня тогда ereg_replace работал дольше и глючил...
Итого:
$contents = str_replace (" \""," «", $contents);
$contents = str_replace ("\n\""," «", $contents);
$contents = str_replace (">\"",">«", $contents);
$contents = ereg_replace ('«([^"]*)"',"«\\1»", $contents);
$contents = str_replace ("«","«", $contents);
Коротко и ясно...
... ну ладно, просто «коротко»...
Как и полагается – known bugs. Известные ошибки. Если на вашем сайте размещаются
примеры скриптов, (как у меня, например) то могут быть проблемы в том случае,
если где-то в теле скрипта после пробела стоит кавычка. Решение – перед
кавычкой. Либо думайте сами. (С html-ем и примерами из него проблем нет).
Еще баг: «http://spectator.ru«.
И еще один – когда кавычки в кавычках: «И он сказал: «Я пришел
к вам...», – ну и так далее''. Самая последняя кавычка обрабатывается некорректно.
PS. Данный пример описан и сделан только в качестве развлечения для автора,
он (автор) ни в коем случае не уговаривает никого переходить на такие «
» кавычки. Исправления принимаются.
ps/ в качестве примера я вставил пока эти строчки в мой движок, посмотрите,
какие во всех заметках стали кавычки.
p.p.s/ Немного поколдовал. Этот вариант лишен двух багов – когда внутри кавычек
содержатся тэги и бага с кавычками внути кавычек.
$contents = str_replace (" \""," «", $contents);
$contents = str_replace ("\n\""," «", $contents);
$contents = ereg_replace ('«([^"]*)"',"«\\1»", $contents);
$contents = str_replace (">\"",">«", $contents);
$contents = ereg_replace ('«([^"]*)"',"«\\1»", $contents);
$contents = str_replace ("«","«", $contents);
Работает примерно на 7% медленней. У кого есть добавления – присылайте.
p.p.p.s. Кстати, там
же написано:
То и дело вместо тире в интернете можно видеть знак дефиса (минус
в верхнем ряду клавиатуры), что неверно; либо – два подряд дефиса, что не необходимо.
Код длинного тире (в полиграфии его называют Em Dash, т. е. «тире шириной
с букву m») – Alt-0151. Чтобы его набрать, нужно прижать кнопку Alt и, не отпуская,
набрать на цифровой** клавиатуре 0151.
Замену «неправильных» тире на правильные можно сделать совсем просто
– «правильные» тире – это те, которые с двух сторон окружены пробелы.
Их и меняем на «Em Dash».
Автор: Дмитрий Смирнов
Информация взята с сайта Spectator