I'm trying to make it so that if the ending of a URL contains anything surrounding a number (except that the first part can be any combination of numbers, a hyphen or a p), then the url is redirected with whatever surrounding the number is taken off.
Here's my regex:
RewriteRule ^all/[^p^P^0-9^\-]+([0-9]+).*$ /allof/$1 [R=301,NC,L]
If I tried these test URLs, the redirect should happen, but does not:
http://example.com/all/-a*1
http://example.com/all/plus100
If I tried this test URL, the redirect does not happen which is correct:
http://example.com/all/p1-100
If I tried these test URLs, the redirect happens, which is correct:
http://example.com/all/(100) - redirects to http://example.com/allof/100
http://example.com/all/minus100 - redirects to http://example.com/allof/100
Perhaps my regex is faulty. I tried removing the extra carets in the square brackets except for the first, and that didn't help, and I don't want to replace the square brackets with only a .* since I then won't be able to capture the number. What could I be doing wrong?
You can use negative lookahead in your rule:
RewriteRule ^all/(?!p\d*-)\D*(\d+) /allof/$1 [R=301,NC,L]
RegEx Demo
Related
I am redirecting certain urls with path to get variables like the following:
localhost2/post/myTitle => localhost2/post.php?title=myTitle
localhost2/post/123 => localhost2/post.php?id=123
So In my htaccess file, I use
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^post/(\d+) post.php?id=$1
RewriteRule ^post/(.*) post.php?title=$1
</IfModule>
This works no problem. But I want to learn how to write negative of ^post/(\d+), that is ^post/(NEGATE-ONLY-NUMBERS). In other words I want a regex that matches the whole input sting if there is not only numbers after post/. So post/abc, post/a23, post/ab3, post/12c and post/a2c should all pass but not post/123. I refered to this post, which suggest using:
(?!^\d+$)^.+$
I can't use ^post/(?!^\d+$)^.+$, because there can be only one ^ and one $. I don't know what regex anchor specifies first position in a substring. My best guess is
post\/(?!\d++).*
I think (?!\d++), with the ++ would eat all characters followig and check if all are digits. But this fails at post/1ab.
Another guess is:
post\/(?![\d,\/]+$).*
The works the best but it allows: post/3455/X.
Secondly, eventually I need to convert localhost2/post/myTitle/123 => localhost2/post.php?title=myTitle&repeat=123 as well. I ave come up with the following:
^post/(?!\d+($|/))(.+?($|/))(\d+$)?
Note: +? to use lazy quantifier, otherwise multiple slashes will be matched by .
and
^post/(?!\d+($|/))([^/\n\r]+($|/))(\d+$)?
Here I use [^/\n\r] instead of .+?
Patterns inside zero-width assertions like (?!\d++) are non-consuming, they do not "eat" chars, they only check the context while keeping the regex index at the same location as before matching the zero-width assertion pattern.
You can use any of the following:
^post/(?!\d+(?:/|$)).*
^post/(?!\d+(?=/|$)).*
^post/(?!\d+(?![^/])).*
See the regex demo. Details:
^post/ - start of input, post/ literal string
(?!\d+(?=/|$)) - a negative lookahead that fails the match if, immediately to the right of the current location, there are one or more digits followed with / or end of string
.* - the rest of the input.
Do not over complicate things when you can keep things simple by keeping 3 separate rewrite rules and since your query parameters are named differently you will need 3 separate rewrite rules anyway.
Consider:
Options -MultiViews
RewriteEngine On
RewriteRule ^post/(\d+) post.php?id=$1 [L,QSA,NC]
RewriteRule ^post/([^/]+)/(\d+) post.php?title=$1&repeat=$2 [L,QSA,NC]
RewriteRule ^post/([^/]*) post.php?title=$1 [L,QSA,NC]
Take note of Options -MultiViews. If this is not enabled in Apache config you must have it here otherwise it will keep all $_GET parameters empty in your php file.
Option MultiViews (see http://httpd.apache.org/docs/2.4/content-negotiation.html) is used by Apache's content negotiation module that runs before mod_rewrite and makes Apache server match extensions of files. So if /file is the URL then Apache will serve /file.html.
I use a RedirectMatch rule which should exclude the following two URLs:
citycards/citycards-locations/munchen/citycards-trachtenvogl-reichenbachstr-47-munchen
citycards/citycards-locations/munchen/citycards-4-you-munchen-hirtenstrasse-18-munchen
I use this rule with regex, but I get a 500 Internal Server Error:
RedirectMatch 301 /citycards/citycards-locations/muenchen/((?!citycards/citycards-locations/munchen/citycards-trachtenvogl-reichenbachstr-47-munchen|citycards/citycards-locations/munchen/citycards-4-you-munchen-hirtenstrasse-18-munchen ).+)$ /citycards/citycards-locations/muenchen/$1
Any ideas why it doesn't work?
Your rule currently is: (broken down to multiple lines for better display/understanding):
RedirectMatch
301
/citycards/citycards-locations/muenchen/((?!citycards/citycards-locations/munchen/citycards-trachtenvogl-reichenbachstr-47-munchen|citycards/citycards-locations/munchen/citycards-4-you-munchen-hirtenstrasse-18-munchen ).+)$
/citycards/citycards-locations/muenchen/$1
Basically, your regex says that:
match /citycards/citycards-locations/muenchen/
which is not followed by either of the following
citycards/citycards-locations/munchen/citycards-trachtenvogl-reichenbachstr-47-munchen,
citycards/citycards-locations/munchen/citycards-4-you-munchen-hirtenstrasse-18-munchen (it has a space after 18-munchen)
match everything until the end of URI
and redirect the matched URI to: /citycards/citycards-locations/muenchen/$1 which is basically the same URL that was matched against.
I see 2 issues.
If the blank space in your negative lookahead is not considered as a part of the pattern, you are essentially passing 4 arguments to RedirectMatch directive, leading to status 500 error
If the pattern is getting parsed correctly, you have an infinite redirection loop.
/citycards-4-you-munchen-hirtenstrasse-18-munchen ).+)$
You have an unescaped space near the end of your RewriteRule pattern. This will certainly cause a 500 error since the space is a delimiter and the arguments will not match up (invalid flags).
It looks like this is a typo and should simply be removed?
I'm new to regular expressions and need to rewrite an example URL:
http://domain.com/quiz.php?id=1
To the friendly URL,which looks like forum URL, like this:
http://domain.com/1-quiz-title
So 1 is the GET variable. Title must be lowercase only
I tried the following but it seems incorrect:
RewriteRule ^([a-z0-9\-]+)$ quiz.php?id=$1 [L]
It's picking the GET variable as 1-quiz-title while it should be only 1
Thanks
If the get variable is only numbers, you want the regex to be like this:
RewriteRule ^([0-9]+)- quiz.php?id=$1 [L]
So the regex matches some amount of numbers first and groups it (the parentheses), the matches a "-". Note that there isn't a $ for end of match, this is essentially going to ignore the title completely, not even going to try to match it. The title doesn't need to be in the rewritten URL so we don't really care what comes after the -.
I have always struggled with regex, and after reading up on it for 45 mins my head is spinning. Negative lookaheads, what the...? (?:/(?:(?!s\d+).)*)+$<--- OMG!!!
:(
So, I have a rule
RewriteRule /([0-9]+) /?id=$1 [R]
and it works fine when the url is www.hi.com/123
How can I make it refresh to / (the document root i nthis case) if the url is www.hi.com/123abc or www.hi.com/a123bc?
I just want to make sure only urls with numbers and nothing else are matched.
I tried
RewriteRule /([0-9]+)([^a-z]+) /map.htm?marker=$1 [R]
But that refreshes towww.hi.com/?id=404, oddly enough.
To match 1 or more numbers in regex it will be:
[0-9]+
To match 1 or more numbers or letters in regex it will be:
[0-9a-zA-z]+
For your case RewriteRule rule will be:
RewriteRule ^([0-9a-z]+)/?$ /map.htm?marker=$1 [NC,L,R=302]
which will match /123abc OR /123abc/ OR /123 OR /abc/, note that trailing slash is optional. Flags I used are:
NC - Ignore Case
L - Last
R=301 - Use http status 302 for resulting URL
I would strongly suggest you reading mod_rewrite Reference doc: Apache mod_rewrite Introduction
However you also asked:
How can I make it refresh to / (the document root i nthis case) if the
url is www.hi.com/123abc or www.hi.com/a123bc?
That rule would be:
RewriteRule ^([0-9a-z]+)/?$ / [NC,L,R=302]
I have an interesting RewriteRule and I am not sure to make the regular expression.
In short I would like to examine the URL after the second / - based on the contents, possibly forward.
It sums down to these two rules:
Redirect if string after second / contains any letter
Redirect if string after second / is longer than 7 characters
Here are examples:
http://www.mysite.org/section/subsection/2011 (OK, do nothing)
http://www.mysite.org/section/subsection/2011-11 (OK, do nothing)
http://www.mysite.org/section/subsection/2011-11-09 (NOT OK, redirect)
http://www.mysite.org/section/subsection/2011-11-W1 (NOT OK, redirect)
Please help me with the Rewrite Rule and Rewrite Cond
I based the following regex off of your examples which seemed to analyze everything after the last '/' instead of the second.
/[^A-Za-z]{1,7}$
In plain English, this regex matches a group of characters that follows a '/' and contains 1-7 non-alphabetical characters. To make it only match the last '/' I appended a '$', which matches the end of a line.
Also, since you are dealing with URLs you might want to add "/?" before the '$' in case there is a dangling '/' at the end.
/[^A-Za-z]{1,7}/?$
I hope this answers your question.
As Lane Aasen points out, your examples and rules don't match up. I'm taking your examples to mean that the rules should apply to the 3rd path segment, and suggest the following. You don't say whether the redirect destination is different or not depending which rule matches. I've taken it to be different.
RewriteEngine on
# redirect if any letter is contained in 3rd part of path
RewriteRule ^([^/]+/){2}.*[a-zA-Z] http://www.bbc.co.uk [R=permanent,L]
# redirect if there are more than 7 characters in 3rd part of the path
RewriteRule ^([^/]+/){2}.{7,} http://www.ibm.com [R=permanent,L]