views:

335

answers:

3

I need to have all _ (underscores) in every url to be replaced with - (hyphens)

I currently do it this way, but am looking for a more simpler way of doing this so I do not have to add a line every time a url gets longer.

RewriteRule ^([^_]+)-([^_]+)-([^_]+)-([^_]+)-([^_]+)-([^_]+)-([^.]+)-([^.]+)-([^.]+)-([^.]+)$ index.php?/$1_$2_$3_$4_$5_$6_$7_$8_$10 [L]
RewriteRule ^([^_]+)-([^_]+)-([^_]+)-([^_]+)-([^_]+)-([^_]+)-([^.]+)-([^.]+)-([^.]+)$ index.php?/$1_$2_$3_$4_$5_$6_$7_$8_$9 [L]
RewriteRule ^([^_]+)-([^_]+)-([^_]+)-([^_]+)-([^_]+)-([^_]+)-([^.]+)-([^.]+)$ index.php?/$1_$2_$3_$4_$5_$6_$7_$8 [L]
RewriteRule ^([^_]+)-([^_]+)-([^_]+)-([^_]+)-([^_]+)-([^_]+)-([^.]+)$ index.php?/$1_$2_$3_$4_$5_$6_$7 [L]
RewriteRule ^([^_]+)-([^_]+)-([^_]+)-([^_]+)-([^_]+)-([^.]+)$ index.php?/$1_$2_$3_$4_$5_$6 [L]
RewriteRule ^([^_]+)-([^_]+)-([^_]+)-([^_]+)-([^.]+)$ index.php?/$1_$2_$3_$4_$5 [L]
RewriteRule ^([^_]+)-([^_]+)-([^_]+)-([^.]+)$ index.php?/$1_$2_$3_$4 [L]
RewriteRule ^([^_]+)-([^_]+)-([^.]+)$ index.php?/$1_$2_$3 [L]
RewriteRule ^([^_]+)-([^.]+)$ index.php?/$1_$2 [L]

Thanks.

A: 

mod_rewrite is not a good tool for that kind of work. Why don’t you replace with PHP?

$_SERVER['QUERY_STRING'] = str_replace('_', '-', $_SERVER['QUERY_STRING']);

Edit    Well you could try these rule sets:

# using the path
RewriteRule ^([^-]+)-([^-]+-.+) /$1_$2 [N]
RewriteRule ^([^-]+)-(.+) index.php?/$1_$2 [L]

# using the query
RewriteRule ^([^-]+)-(.+) index.php?/$1_$2
RewriteCond %{QUERY_STRING} ^([^-]+)-(.+)
RewriteRule ^index\.php$ ?$1_$2 [N]
RewriteRule ^index\.php$ - [L]

But be careful with the N flag as you can easily get an infinite recursion.

Gumbo
I am using Codeigniter, so the urls have to have _ in them to reference the controller functions. function new_page() {} can not be function new-page() {}. So the urls just need to show up different in the browser url.
Will Ayers
Is that the same as I have above, since you are only have $1 and $2. I have the possibility of having over 10 _ needing to be replaced with -
Will Ayers
@Will Ayers: The *N* flag will take care of it and loop as long as the rule is applied. But as I said, mod_rewrite is not the best tool to do such things as using *N* is dangerous.
Gumbo
Is there a way to set a max to N? or could I replace N with a number like 20?
Will Ayers
@Will Ayers: No, rules with *N* will restart the rewrite process everytime the rule is applied. There is no counter that can stop it. That’s the dangerous thing about the *N* flag. But unlike the *L* flag, the *N* flag does not generate an internal redirect that are limited and thus can replace an arbitrary number of hyphens.
Gumbo
A: 

sedhyphen.sh:

#!/bin/sh
sed -u 's/_/-/g'

httpd conf:

RewriteMap sed-hyphen prg:sedhyphen.sh
RewriteRule ^(.*)$ index.php?/${sed-hyphen:$1} [L]

Make sure that sedhyphen.sh is set executable.

Ignacio Vazquez-Abrams
Could you explain where I am putting the code sedhyphen.sh and the code #!/bin/sh and sed -u 's/_/-/g'
Will Ayers
sedhyphen.sh is a separate shell script you create. It should go somewhere in `$PATH`.
Ignacio Vazquez-Abrams
can this file be hosted nn the server like a regualr file with ftp? or do I need to use ssh to install on the server its self?
Will Ayers
Not all FTP servers support the `chmod` command, so you may need to use ssh to set it executable.
Ignacio Vazquez-Abrams
A: 

Perhaps this:

RewriteCond %{REQUEST_URI} ^(.*)_(.*)/$
RewriteRule (.*)_(.*)/ http://your-site.com$1-$2/ [R=301]
Steve Kemp
While this will work, it will result in one extra HTTP exchange per underscore.
Ignacio Vazquez-Abrams