Он убирает неправильные ссылки со страниц, но не дает 404 для тех, которые уже проиндексировались
Я ничего не понял из вышенаписанной сумбурности. Этот replace ничего не убирает. Он просто добавляет стартовый слэш к штатным ссылкам на странице, чтобы они были "условно абсолютными" (от корня), а не относительными (от места вызова). В ShopCMS без ЧПУ этой проблемы нет вообще, т.к. там ВСЕ ссылки идут от корня, поэтому штатные ссылки без слэша, там он избыточен.
Мне кажется, что Вы путаете две проблемы - дописывание слэша к штатным ссылкам (выше я уже писал, зачем это надо) и множественность правильно разрешаемых ссылок. Одно к другому никакого отношения не имеет.
Отдельно интересно, каким это образом поисковики успели проиндексировать неправильные ссылки?
Решение проблемы множественных правильных ссылок (/page_1.html и /xxxx/page_1.html/yyyyy/ - редирект в одну и ту же ссылку):
в файле index.php
1. заменяем
define('CATEGORY_PATTERN','/\/?(category_(\d+)((_offset_(\d+))|(_show_all))?\.html)/');
define('PRODUCT_PATTERN' ,'/\/?(product_(\d+)\.html)/');
define('PAGE_PATTERN' ,'/\/?(page_(\d+)\.html)/');
define('NEWS_PATTERN' ,'/\/?(show_news_(\d+)\.html)/');
на
define('FROM_CATEGORY_PATTERN','/^\/?(category_(\d+)((_offset_(\d+))|(_show_all))?\.html)$/');
define('FROM_PRODUCT_PATTERN' ,'/^\/?(product_(\d+)\.html)$/');
define('FROM_PAGE_PATTERN' ,'/^\/?(page_(\d+)\.html)$/');
define('FROM_NEWS_PATTERN' ,'/^\/?(show_news_(\d+)\.html)$/');
define('TO_CATEGORY_PATTERN','/\/?(category_(\d+)((_offset_(\d+))|(_show_all))?\.html)/');
define('TO_PRODUCT_PATTERN' ,'/\/?(product_(\d+)\.html)/');
define('TO_PAGE_PATTERN' ,'/\/?(page_(\d+)\.html)/');
define('TO_NEWS_PATTERN' ,'/\/?(show_news_(\d+)\.html)/');
2. в функции replace_from_cpu заменяем вышеизмененные *_PATTERN на FROM_*_PATTERN
3. в функции replace_to_cpu заменяем вышеизмененные *_PATTERN на TO_*_PATTERN
Это не совсем оптимально, т.к. шаблоны практически повторяются и можно бы подумать, но думать лень
.