Javascript-форум (https://javascript.ru/forum/)
-   Серверные языки и технологии (https://javascript.ru/forum/server/)
-   -   Запрос MySQL с регуляркой (https://javascript.ru/forum/server/78048-zapros-mysql-s-regulyarkojj.html)

MC-XOBAHCK 19.07.2019 16:01

Запрос MySQL с регуляркой
 
Здравствуйте! Прошу помощи написать запрос для MySQL с регулярным выражением.

Нужно в содержимом столбца найти атрибуты href="..." и проставить в них перед значениями слеш, при условии что значение не начинается с http или со слеша /

Опишу суть подробнее.
В БД у меня есть таблица articles. В этой таблице есть столбец content
В столбце content хранится html статей.

Проблема в том, что в статьях есть ссылки на внутренние страницы сайта. Прописаны они без домена и перед ними нет слеша. Пример таких ссылок:
<a href="forum">Форум JavaScript</a>
<a href="forum/misc>Общие вопросы</a>
<a href="forum/server>Серверные языки и технологии</a>


До сих пор отсутствие слеша мне не мешало и всё работало. Но теперь сайт переезжает и нужно в таких значениях проставить слеши, то есть чтобы стало так:
<a href="/forum">Форум JavaScript</a>
<a href="/forum/misc>Общие вопросы</a>
<a href="/forum/server>Серверные языки и технологии</a>


Для поиска есть такая статическая часть:
[ href="]
вначале есть пробел, а в конце - одна двойная кавычка.
После кавычки идут английские буквы.
Если в начале значения уже есть слеш / или значение начинается с http то такие ссылки пропускаем (не нужно ставить слеш).

Помогите пожалуйста написать такой запрос.

MC-XOBAHCK 19.07.2019 16:06

Что то похожее я уже сделал для атрибута src в изображениях <img src="..." />

Вот такой запрос:
UPDATE `articles` SET `content` = REPLACE(content, 'src="images/', 'src="/images/')


Но тут у меня был статический параметр images (папка с изображениями) и я смог с этим справиться самостоятельно.

laimas 19.07.2019 17:07

Цитата:

Сообщение от MC-XOBAHCK
Запрос MySQL с регуляркой

А стоит ли это делать в свете переезда? Если переезжаем, значит заменить нужно один раз, следовательно выгоднее взять как есть из базы, средствами серверного скрипта заменить все на нужное и сохранить. Не знаю, что у вас за серверный язык, но в нем рег. выражения намного богаче.

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

PS. Если только слеш подставить, то меняйте href=" на href="/.

MC-XOBAHCK 19.07.2019 19:17

laimas, скажите пожалуйста, а в MySQL сделать такое вообще возможно?


Цитата:

Сообщение от laimas
PS. Если только слеш подставить, то меняйте href=" на href="/.

Так нельзя делать. А если значение href начинается с http, например href="https://javascript.ru", то тогда слеш поставиться в самом начале и ссылка сломается. Или если уже есть слеш, то их станет два что тоже плачевно для меня.


У меня php 7.2. Переезжает сайт - это я его с joomla переношу на OctoberCMS (laravel). Статьи импортирую со старого сайта на новый.
С регулярками у меня беда - я за помощью часто на форуме обращаюсь по ним.
В php вообще никогда регулярки не писал.

Если это поможет, вот функция импорта:
public function importData($results, $sessionKey = null)
    {
        $firstRow = reset($results);

        foreach ($results as $row => $data) {
            try {

                // Создаем новую запись
                $item = Item::make();

                // Исключить из цикла 
                $except = ['id']; // В этом массиве мы исключаем те переменные, которые не нужно обрабатывать в автоматическом цикле foreach ниже

                // Цикл заполнения
                foreach (array_except($data, $except) as $attribute => $value) {
                    $item->{$attribute} = $value ?: null; // Присваивание значения в столбец по атрибуту
                }
                // Сохранение
                $item->save();
                
                $this->logCreated();
            }
            catch (\Exception $ex) {
                // Ошибка
                $this->logError($row, $ex);
            }

        }
    }

laimas 19.07.2019 19:40

Можно и в SQL - http://www.mysql.ru/docs/man/Regexp.html , в нем не очень то и много, но простейшее сделать можно. Можно вообще и строковыми функциями обойтись.

Но к примеру. Это у вас html со ссылками, да еще и с внутренними. Предположим, что N страниц "умерло", что тогда, выставлять битые ссылки или руками править? Хорошо если страница можно сказать статика, но если она ссылается на динамический контент, тогда могут быть неприятности. В таких случаях ссылки определяются как параметры страницы, которые подставляются при выводе. Если страница умерла или изменила адрес, то либо не будет ссылки, либо будет новый адрес. Хотя хозяину виднее.

MC-XOBAHCK 19.07.2019 20:05

У меня эта страница по ссылке уже два дня в браузере открыта. У меня практики нет, поэтому я теряюсь в документации. Написать запрос самостоятельно я не могу.

Почему мне это надо? Если раньше с относительными путями без слеша в начале работало всё нормально, то с переездом если нет вначале слеша, то к пути добавляется вначало путь просматриваемой страницы. В общем вся внутренняя перелинковка на сайте падает, а 404-ая становится самой популярной.

laimas 19.07.2019 20:19

Так что у вас в ссылках - только относительные пути или же есть и абсолютные?

PS. Учтите, что MySQL может найти запись по рег. выражению, заменять же им он не может, то есть без костыля тут никак не обойтись. Почему я и говорил об однократном запуске простого скрипта - получили записи, заменили посредством РНР, сохранили.

MC-XOBAHCK 19.07.2019 20:37

Есть относительные такого вида без слеша:
<a href="forum/server>Серверные языки и технологии</a>


Есть со слешем:
<a href="/forum/server>Серверные языки и технологии</a>


Есть с полными путями (они на внешние ресурсы):
<a href="https://javascript.ru/forum/server>Серверные языки и технологии</a>



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

laimas 19.07.2019 21:06

Написать простенький скрипт, который запустить один раз не проблема? В нем запрос - получить все всех записей (объем таблицы позволит?), затем обходом готовим массив, заменяя в нужном поле ссылки:

$s = preg_replace ('/href="(?!\/|https?)/m', 'href="/', $s);


где $s, это значение этого поля.

Затем очищаем таблицу (TRUNCATE), после чего многострочной вставкой заносим массив с изменениями. Можно, конечно, в цикле и обновлять только одно значение полученное запросом, но это более накладная операция.

MC-XOBAHCK 19.07.2019 21:44

laimas, Спасибо!
Я идею понял. В ларавеле там с запросами не сложно. Буду пробовать.


Часовой пояс GMT +3, время: 08:01.