Как сделать замену кавычек на «елочки» через регулярку?
Доброго времени суток, уважаемые!
Возникла необходимость сделать при обработке текста замену прямых скобок (") на красивые елочки («ёлочки» ).
То есть, имеется текст: "Он сказал, - поехали"
"Он сказал поехали!"
"Он сказал - поехали?"
"Он сказал поехали?!"
"Он сказал поехали..."
"Он сказал "поехали"
где надо всё поменять на «Он сказал, — поехали»
«Он сказал поехали!»
«Он сказал — поехали?»
«Он сказал поехали?!»
«Он сказал поехали...»
«Он сказал «поехали»
Так как сам я нуб нубом, то полез искать, как это делается умными людьми.
Нашел вполне рабочую регулярку:
$datatext = preg_replace('#"(.*?)"#', '«$1»', $datatext);
Она работает, всё хорошо, но!
Вот в этом случае (когда внутри кавычек присутствует ещё одна): "Он сказал "поехали"
результат получается: «Он сказал »поехали"
Что неприемлимо, увы.
Но мы же, нубочайники, не привыкли отступать!
После применения альтернативного мЫшления было решено разбить задачу на составляющие. То есть, сделать две регулярки. Первая заменяет кавычку в начале слова, а потом, уже вторая, в конце слова.
$datatext=preg_replace('/\B\"\b/','«',$datatext); // в начале
$datatext = preg_replace('/\b(.*?)"/', '$1»', $datatext); // в конце
Что самое удивительное, эта вот конструкция работает! Но вставлять её в сайт страшно. Поскольку я слабо понимаю как она работает (особенно второе выражение), и чем это может грозить.
Поэтому огромная просьба к опытным людям, дать оценку этому художеству на предмет безопасности/производительности.
Вроде: "Написано левой ногой через правое ухо, но в принципе ничего опасного, вставляй на свой сайтик и не надоедай больше"
Или же: "Нубас, если ты вот это убожество вставишь (неважно куда) базы рухнут, сервер повиснет и к тебе хостеры с бейсбольными битами прибегут! Так что, сотри немедленно и больше никому не показывай!"
Заранее благодарю за ответ.
xmoonlight:
*шмыгает носом* за что Вы уж так то? Чайник, но не настолько же!
файл:
<?php
$datatext='"Он сказал, - поехали"';
$datatext=preg_replace_callback(
'#((^|\s)\".)|(.\"($|\s))#u',
function ($matches) {
if ($matches[1]) return str_replace('"',"«",$matches[1]);
else return str_replace('"',"»",$matches[3]);
},
$datatext
);
echo "проба: ".$datatext."";
?>
На выходе получаем страницу с html:
проба:
xmoonlight:
Понял, осознал, чайник =))
Нет, у меня по умолчанию файл а ANSI был (редактор так настроен), сейчас перекодировал в UTF-8 всё заработало.
Огромное спасибо!
Осталось чегонить с кодировкой придумать, поскольку сайт на нубском cp1251
kotey: #..#u -
u - означает юникод. уберите u и будет работать в однобайтовой кодировке. (но я не советую, только если у вас всё в однобайтовой).
в общем, переходите на UTF-8 чем быстрее, тем лучше.
xmoonlight: понял, спасибо! (увы, всё в однобайтовой)
upd:
Я счас застрелюсь. С удалением "U" скрипт кривляться перестал, НО
если в начале текста ставится тег (то есть, знак вместо пробела, кавычка опять не обрабатывается) <tab>"Он сказал, — поехали»
Господибожемой, это не кончится ни-ког-да!
Простите, бога ради, понимаю, что утомил уже своей тупизной, но вот это вот
$datatext=preg_replace('/\B\"\b/','«',$datatext); // в начале
$datatext = preg_replace('/\b(.*?)"/', '$1»', $datatext); // в конце
совсем ужас, или сойдет? Понимаете, оно всё же работает, и хоть в общих (сильно общих) я знаю как оно работает. А больших текстов на обработку не предвидится.
xmoonlight: Ох, огроменннннное спасибо!
Там только один нюанс (я уже почти стрелялся, но осечка вышла, пришлось чуть подумать)
В коде функции в условии else
function ($matches) {
if ($matches[1]) return str_replace('"',"«",$matches[1]);
else return str_replace('"',"»",$matches[2]);
},
если указано $matches[3] обрезается последний символ в слове, то есть из "Он сказал, — поехали"
возвращает «Он сказал, — поехал
НО, если изменить на $matches[2] всё работает. Кажется.
upd
Только одиночные буквы обрабатывать не хочет.
из "б"
возвращает «б"
а из
"б" "пробник"
выводит
«б« «пробник»
Ну да черт с ним, это редко попадается.
Ещё раз спасибо! Извините, что отнял столько времени.
Да там мелкая плюшка, просто, что бы уж совсем экзотичные варианты учесть.
Исходная строка: $datatext='"7" "444 "888"
"а" "ддд "жжж"';
если регулярка '#((?![A-Za-zА-Яа-яЁё])\")|(.\"(?![A-Za-zА-Яа-яЁё]))#u'
то возвращает «7» »444 »888»
«а» «ддд «жжж»
если добавляем в условия цифры '#((?![A-Za-zА-Яа-яЁё0-9])\")|(.\"(?![A-Za-zА-Яа-яЁё0-9]))#u'
то получаем, корректные елочки и с цифрами «7» «444 «888»
«а» «ддд «жжж»
kotey: выражение '#(([\"]{2,})|(?![^\W])(\"))|(.\"(?![\w]))#u', вроде работает как по старому варианту... код целиком заменили?
с "бабочкой" - пока разбираюсь....
kotey: ясн)) ну главное, чтобы Ваша задача решилась и к этому куску кода - больше не возвращаться. Просто всегда все функции/классы стараюсь до максимума всё делать, чтобы потом не переделывать, а только использовать.
xmoonlight: А-а. Понятно. Только не помню подобных примеров. Надо ли?
Я вот про другое сейчас подумал. А если научить эту функцию кавычки в тегах пропускать не обрабатывая? Чтобы не только текст, но и с тегами можно было через неё прогонять.
Или плохая идея? Оно ведь и в тексте может встретиться фраза вроде: он сказал <точнее "подумал"> "поехали!"
разве что выключатель через radio прикрутить. Типа установил в режим html - пропускает, установил "текст" - обрабатывает.
xmoonlight: Подумав ещё. Ну, получается, что надо как-то
IF (тут проверяем положение radio) если "текст" то задействуем вот эту, из Вашего ответа, которая всё подряд ёлочит
ELSE
другую регулярку, которая кавычки между уголками будет пропускать <тег и атрибуты всякие>.
з.ы. даже не radio тогда, а чекбокс. Поставил галку "пропускать теги" и всё, можно "елочить" текст с тегами, теги сохранятся
xmoonlight: Имхо, не стоит. Ненужное усложнение. Ссылки в внутри JS мало того, что редкость, так и довольно специфичны и в самом тексте обычно не отображаются. Так какой смысл с ними возиться?
kotey: ну, наверно, да.... а ёлочные кавычки - Вам вообще для каких текстов потребовались зачем вообще-то это?
Я предположил, что для оформления блога в книгу или вёрстка книг для печатного издания... Другое - даже не могу предположить....
xmoonlight: Для оформления текстов. То есть, есть предположим вордовский документ и его надо разместить на СИ
Тут вырезаем лишние строки, а в начале абзацев делаем "красную строку" размещая тег < dd >, если этот же текст надо выложить на BB-форуме, то вместо тега делаем "красную строку" тройным пробелом, если на ФБ то делаем тегом < tab >.
И вот чтобы не париться со всем этим вручную есть примитивно-нубский скрипт, который делает всё это в один клик.
Ну, он там ещё минусы где надо меняет на "длинное" тире, вырезает лишние пробелы и пустые строки... Фигня, короче, но КАК облегчает жизнь, Вы не представляете. И вот тут вот пришло в голову допилить "елочки", чтобы если текст перекидываешь с СИ (где по умолчанию любые кавычки переводятся в двойные) на ФБ, возвращались красивые елочки.
xmoonlight: Сорь, просто СИшники часто забывают, что кроме них, графоманов, есть и нормальные люди, которым "СИ" (произносить с придыханием или презрительно скривившись, в зависимости от отношения) ни о чем не говорит =))
Увы, это решение не работает, поскольку выходит просто пропуск непарной кавычки, плюс обрезание последнего знака. =(
То есть на выходе получаем:
«Он сказал "поехал»
Ну в примере с двумя регулярками все непарные кавычки обрабатываются.
На выходе получаем:
«Он сказал «поехали»
То есть вроде как всё нормально, но: а) регулярок две, б) страшные они какие-то.