On 29 Apr 2005, at 8:33 AM, Andrew Cohill wrote:
I'm baffled....I have reviewed the Drupal guide on the site and read through numerous postings from the archive of this list, and have tediously tested many alternate paths.
I currently have this path (which works)
<^(?!event)>
it used to to keep certain blocks off the month view of the calendar.
I want to add to that string something that does not display a block on a specific page (e.g. node/635)
I tried
<^(node/635)|^(?!event)> (did not work) <(^node/635)|^(?!event)> (did not work)
I'm not sure I am using the vertical bar | correctly. I had trouble finding examples of multiple paths.
I am also not specifying the node/635 correctly, as I could not get to work even when I removed the second part ^(?!event)
Thanks, Andrew
Hi Andrew,
I can empathize with your situation! This is one of the most powerful, but also one of the most difficult, aspects of the block mechanism in Drupal.
Both power and difficultly spring from the same source - *regular expression syntax*. There are entire books on the subject, so please don't feel stupid! It really is pretty heavy going.
You'll want to place the entire regular expression in angle brackets, as in your examples.
The caret (^) *anchors* your regular expression to the start of a line, that is, the part of the URL immediately following the hostname.
Hence <^node> will match http://www.example.com/node, http://www.example.com/node/foo, and http://www.example.com/node/123, if your server is www.example.com.
If you omit this and type <node> for example, your regular expression will match http://www.example.com/node, but also http://www.example.com/nodessert, http://www.example.com/blog/how_to_delete_a_node, etc.
OK so far?
As you have perceived, parentheses *group* sub-expressions (sort of in the same way that parentheses group sub-expressions in arithmetic, or even in written communication, as in this example!). The 'pipe' operator (|) is used to separate alternatives. Read it as 'or'. So,
<^(foo)|(bar)>
can be read as 'match foo or bar at the start of the line'.
The expression (?!...) is called a negative look-ahead operator. It says to match only if the subexpression following the ?! does not match from the point where the ?! is evaluated (matched)
So <^foo(?!(t))> matches http://www.example.com/fool and http://www.example.com/fooze but not http://www.example.com/foot, or http://www.example.com/football.
One more thing - letters and numbers 'match themselves', but obviously certain other special characters have special meaning (e.g., we've already seen that ^,?, !, | and parentheses are treated specially). These are called *metacharacters*. To match a metacharacter you need to 'escape' it, by preceding it with a '' (backslash). So, to match the pattern 'foo?!' you'd have to type <foo?!>.
Now, we can put all of the pieces together. Just as in arithmetic, or in writing compound sentences, you can create long expressions by combining short ones. Regular expressions can be combined by simply catenating them: <foo> matches 'foo', and <bar> matches 'bar'; catenate them to get <foobar> matching 'foobar'. You can also combine by alternation: <(foo)|(bar)> matches foo or bar. You can specify that a subexpressions matches zero or more times by following it with an asterisk: <(foo)*t> matches 't', foot, foofoot, foofoofoot, and so on. (I've omitted the server part of the URL for brevity)
On to your example:
<^(?!(node/635)|(event))>
matches (at the beginning of the line) anything that doesn't match the subexpression following ?!, namely, node/635, or event. I've escaped the slash - I don't know if this is necessary (but it doesn't hurt - any regular character when escaped just matches itself)
If you're beginning to love this stuff, there's hundreds of more pages of fun examples in various books and on other websites (for example at http://www.php.net). Just search for 'regular expression' or PCRE (perl compatible regular expressions)
Hope this helps,
Djun