mod_rewrite: заменить подчеркивание тире

Я раскрываю мое смущающее незнание REGEX-фу здесь, но: у меня в настоящее время есть веб-сайт, где загружено множество статей ». URL пишутся какarticle_name»в то время как новые написаны какСтатья-наме».

Я хочу перевести все из них на использование тире, поэтому есть ли регулярное выражение, которое я мог бы использовать, чтобы переписать старые URL-адреса в более новые эквиваленты?

Заранее спасибо!

Ответы на вопрос(5)

Потенциально иной подход к размышлению: я

м при условии, что ваш "старый формат " и ваш "новый формат " будет в разных каталогах для этой идеи, если они неВозможно, вы захотите сделать так, чтобы новый формат имел другое имя каталога.

Например:

http://site.com/articles/2008/12/31/new_years_celebration
http://site.com/article/2008/12/31/new-years-celebration

В этом случае вы можете использовать mod_rewrite, чтобы обнаружить что-либо встарый каталог " и перенаправить его на "".redirector.php

Хотя, если подумать, ваш mod_rewrite может выглядеть примерно так:

RedirectRule /articles/(.*_.*)  /redirector.php?article=$1

Сопоставляя что-нибудь с_ и отправив его через редиректор.

Внутри redirector.php вы можете получить$_SERVER['REQUEST_URI'] и использовать такие инструменты, как preg_replace и даже запросы к базе данных, чтобы найти правильный URL-адрес, на который они перенаправляются, а также изучить количество обращений к старым URL-адресам.

 kch14 авг. 2009 г., 22:59
Это может оказаться гораздо более простым решением для реализации.
Решение Вопроса

Сначала вы должны достичь согласованности в существующих URL. По сути, вы должны нормализовать все существующие имена, чтобы всегда использовать тире. Ok Вы'мы сделали это

Мы'начнем со следующего предположения:

URL примерно в форме:

http://example.com/articles/what-ever/really-doesnt_matter/faulty_article_name

где только URL под/articles следует переписать, и только/faulty_article_name часть должна быть продезинфицирована.

Сильно обновленный, с чем-то, что на самом деле работает

Для Apache:

RewriteEngine     On
RewriteRule       ^(/?articles/.*/[^/]*?)_([^/]*?_[^/]*)$ $1-$2 [N]
RewriteRule       ^(/?articles/.*/[^/]*?)_([^/_]*)$       $1-$2 [R=301]

Тот'как правило, вдохновлен GAppleответ.

Первый/? гарантирует, что этот код будет работать как на Vhost Confs и.htaccess файлы. Последний не ожидает ведущего слэша.

Затем я добавляюarticles/ часть, чтобы гарантировать, что правила применяются только для URL-адресов в пределах./articles

Затем, хотя у нас есть по крайней мере два подчеркивания в URL, мы продолжаем цикл по правилам. Когда у нас остается только одно оставшееся подчеркивание, включается второе правило, заменяет его тире и выполняет постоянное перенаправление.

Уф.

 Keith Williams14 авг. 2009 г., 21:56
Нормализация достигнута - яМы только что перешли на новую CMS (WordPress), поэтому все статьи теперь используют тире для пробелов. Правила идут в плагине WordPress для перенаправления контента, который принимает либо статические перенаправления (нене хочу добавлять более 50 отдельных !!) или регулярное выражение.
 kch14 авг. 2009 г., 22:15
Ты имеешь в видуне использую apache 's mod_rewrite? Какие'Это плагин WordPress? Есть ссылка на это? Я'Я хотел бы знать, как именно он делает свои перенаправления. Если бы вы могли обновить ваш вопрос, чтобы указать на этот факт ...
 kch14 авг. 2009 г., 23:14
Ах, теперь до меня дошло, что Apache выигралЕсли вы действительно выполните подстановку, как это делает gsub, он будет ожидать, что вы перехватите элементы, которые вы хотите использовать повторно, и поместите их обратно при создании окончательного URL. Что делает вещи немного сложнее. gnarf»Решение может быть вашим лучшим выбором.
 Keith Williams14 авг. 2009 г., 21:56
Ох, и да - этоs точная структура URL.
 Keith Williams04 сент. 2009 г., 00:00
Извините за долгую задержку - я ушел в отпуск сразу после того, как опубликовал это, только вернулся и попытался. Работал как шарм! Чтобы ответить на ваш вопрос, я нене хочу использовать mod_rewrite, потому что я неУ него нет доступа к файлу конфигурации HTTP (общий хостинг), и WordPress вставляет свой собственный код перенаправления в .htaccess.
 JackTheKnife30 сент. 2015 г., 17:42
Это создает бесконечный цикл перенаправления для меня: \ More here:stackoverflow.com/questions/32852356/...

Как мод переписать будет знать, какой фактический URL должен быть? Вы можете переписать все статьи, чтобы использовать подчеркивание или тире, но нет никакого способа дляmod_rewrite сказать, существует ли новое местоположение.

Например,

/I_Like_Bees      is stored as   /path/i_like_bees
/I-like-flowers   is stored as   /path/i-like-flowers

Ты хочешьi-like-bees переписать на.i_like_bees

Если вы переписываете подчеркивания на тире,i_like_bees Wouldn»не найтиесли переписать тире в подчеркиванияi-like-flowers Wouldn»не найти

Если вы сохраняете все свои статьи последовательно, вы можете легко заставить работать правило переписывания. Вместо этого вам, вероятно, придется написать сценарий для проверки существования каталогов и выполнить перенаправление 301 в нужное место.

 Keith Williams14 авг. 2009 г., 21:57
Извини я неНе совсем понятно - все статьи будут нормализованы, я просто хочу установить правила для обработки старых ссылок и предотвращения Linkrot.

Вот's метод:http://yoast.com/apache-rewrite-dash-underscore/

По сути, он разделяет URL на токены по обе стороны от подчеркивания и снова переписывает токены с заменой подчеркивания. Проблема в том, что он заменяет только одно подчеркивание за раз; он будет перенаправлять на более близкий, но не совсем правильный URL, который снова будет перенаправлять на еще более близкий, но, возможно, все еще не правильный URL ...

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

Не забудьте добавить любые квалификаторы, если можете, однако, так как правило может заменить пути, которые вы не указалиt хотите изменить (например, файлы изображений) как есть.

 kch14 авг. 2009 г., 23:26
И это так. Смотрите мой обновленный ответ.
 kch14 авг. 2009 г., 23:17
Ну, это может сработать, если вместо [R = 301] использовать [N] (для следующего раунда)
 kch14 авг. 2009 г., 23:00
Тот'с "Слишком много перенаправлений ошибка в ожидании Я'буду держаться подальше от этого решения. Это'Умный взлом, но не без проблем.

Попробуй это:

RewriteRule ^([^_]*)_([^_]*_.*) $1-$2 [N]
RewriteRule ^([^_]*)_([^_]*)$ /$1-$2 [L,R=301]

Первое правило заменяет одно подчеркивание за раз, пока не останется один или менее. Последнее правило заменит последнее подчеркивание и выполнит внешнее перенаправление.

 pcworld13 нояб. 2017 г., 05:56
Это, кажется, вызывает бесконечный цикл (сервер неt ответить) для URL-адресов, где по крайней мере два подчеркивания находятся на уровне пути больше 1, например ,http://example.com/a/a_b_c/
 SenG11 сент. 2016 г., 11:26
Можно ли обойтись без перенаправления? Я имею в виду, с HTTP 200, возможно ли сделать это переписать?
 MrWhite23 сент. 2018 г., 19:20
@pcworld Вам может понадобиться добавитьDPI (Discard Path Info) флаг на первомRewriteRule директива, если более ранние сегменты пути не• сопоставить с физическим путем файловой системы (обратите внимание, что завершающий слеш также создает дополнительный сегмент пути). (Префиксзамена с косой чертой, так что он переписывает на URL-путь, в отличие от пути к файловой системе, также может помочь в некоторых сценариях.)
 dpavlin26 авг. 2013 г., 10:35
@Littlered вы правы. Правильная форма этого правила должна быть следующей: RewriteRule ^ ([^ _] *) _ ([^ _] * _. *). Html $ 1- $ 2.html [N] RewriteRule ^ ([^ _] *) _ ([ ^ _] *). html $ /$1-$2.html [L, R = 301], который переписывает только HTML-файлы
 kch15 авг. 2009 г., 00:00
+1 за то, что не забыли добавить косую черту при перенаправлении. Я'Я не уверен, что хочу обновить свой ответ vhost-htaccess-agnostic, чтобы фактически принять это во внимание. О, так много скобок.
 littlered15 февр. 2013 г., 20:05
это убивает мои изображения, в имени которых есть _.

Ваш ответ на вопрос