2

I have this set of rules in my .htaccess and I would like to add additional rule (or change existing) so that all underscores in URLs are rewritten to hyphens.

RewriteEngine on

#1--Redirect  "/?load=/foo" to "/foo"--#
RewriteCond %{THE_REQUEST} /\?load=/([^\s&]+) [NC]
RewriteRule ^ /%1? [NE,L,R]
#2--Rewrite "/foo" to "/?load=/foo--#
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)/?$ /?load=/$1 [NC,L,QSA]

Also, is there a way to limit the number of consecutive hyphens? Rewriting _ to - on some URLs gives me results like file---data---backup, since the original URL had a hyphen between two underscores. Could I somehow turn such URLs into e.g. file-data-backup instead?

Ilmari Karonen
  • 49,047
  • 9
  • 93
  • 153
ah0dev
  • 35
  • 2

2 Answers2

0

You can use an additional redirect rule:

RewriteEngine on

#1 Redirect rule to convert _ to -
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+(.*?)_+[_-]*(.+?)\sHTTP [NC]
RewriteRule ^ /%1-%2 [L,NE,R=302]

#2--Redirect  "/?load=/foo" to "/foo"--#
RewriteCond %{THE_REQUEST} /\?load=/([^\s&]+) [NC]
RewriteRule ^ /%1? [NE,L,R=302]

#3--Rewrite "/foo" to "/?load=/foo--#
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)/?$ /?load=/$1 [L,QSA]
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • Great, works like a charm. Just one additional question: Is there a way to limit the number of hyphens? Since it rewrites _ to - on some url's I get "file---data---backup" form since there was a hypen in between underscores. Could I get somehow "file-data-backup" form? – ah0dev Mar 14 '16 at 16:32
  • It depends on the page/article name. Administrator inserts name with spaces and hypens. For example "tax fees - 2016". Url is then tax_fees_-_2016. With your rule its tax-fees---2016. I would like to remove unecessary hypens somehow dynamicaly if its possible. – ah0dev Mar 14 '16 at 17:53
  • This may work, but it's needlessly complicated and inefficient. The method described e.g. in [this answer](http://stackoverflow.com/a/1279758) is much preferable. – Ilmari Karonen Mar 14 '16 at 18:19
  • @anubhava: As given, it doesn't touch query strings. I don't believe the OP needs that, either, given the URL scheme implied by their existing rules (outward-visible URLs like `/foo-bar-baz`, converted internally to `/?load=foo-bar-baz`). – Ilmari Karonen Mar 14 '16 at 18:28
  • In the absence of information in question OR sample URLs provided I cannot assume that query string should be left unconverted. Secondly that linked answer converts `/tax_fees_-_2016` to `/tax-fees---2016` but OP wants `/tax-fees-2016` – anubhava Mar 14 '16 at 18:47
0

The method described e.g. in this answer should work for you with minor adaptation. Mainly, you'll want to add some RewriteConds to keep it from applying to any URLs corresponding to images and other actual files:

# Replace all but the last underscore with dashes internally:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^_]*)_([^_]*_.*)$ $1-$2 [N]

# Replace the last underscore and issue a HTTP permanent redirect:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^_]*)_([^_]*)$ /$1-$2 [L,R=301]

(Add these rules before your existing rules, but after the RewriteEngine On line. Note that you can leave out the RewriteConds if you know you don't and won't have any actual files with underscores in their names.)

You can also modify these rules to collapse consecutive hyphens:

# Collapse all but one group of multiple hyphens internally:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^-]*(-[^-]+)*)--+([^-]+(-[^-]+)*--.*)$ $1-$3 [N]

# Collapse the last group of hyphens and issue a HTTP permanent redirect:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^-]*(-[^-]+)*)--+([^-]+(-[^-]+)*|)$ /$1-$3 [L,R=301]

or even do both at the same time:

# Collapse all but one group of multiple hyphens and/or underscores internally:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^-_]*(-[^-_]+)*)(--|-_|_)[-_]*([^-_]+(-[^-_]+)*(--|_).*)$ $1-$4 [N]

# Collapse the last group of hyphens and/or underscores and issue a HTTP permanent redirect:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^-_]*(-[^-_]+)*)(--|-_|_)[-_]*([^-_]+(-[^-_]+)*|)$ /$1-$4 [L,R=301]

(Disclaimer: I have not actually tested these rules. I believe they should work, but I might have made a typo somewhere.)

None of these rules affect query strings in any way, which is probably what you want. If you do want to replace underscores and/or multiple consecutive hyphens in query strings, too, you can do it e.g. using the method described on the Apache httpd wiki here.

Community
  • 1
  • 1
Ilmari Karonen
  • 49,047
  • 9
  • 93
  • 153