Trying to match and URL like this


in .htaccess I can match and extract all the groups properly with


in add_rewrite_rule I can not make it match. I've tried escaping the [ with \\[, \\\\[, \\\\\\\\[

and nothing works. I've also tried \Q[\E and using it as \x5b \091 and nothing works. Also tried ([^\\[]+) to match non [ characters up to the [

What's the proper way to match metacharacters like this?? Does the same for literal \()


I've found this to be one of the more poorly documented features of WordPress, so hopefully this is on track or will be corrected by someone more fluent in WP_Rewrite.

The basic gist is thus:

  1. During plugin activation and when flushing rules, ensure your custom rule is added to the list.
  2. During init, use add_rewrite_tag() for any custom query string parameters that are in the rule. For a destination of index.php?this_is_custom=$matches[1], you must add the this_is_custom tag.
function wpse_39626_init() {
    // these must be added during init. if you haven't done
    // add_rewrite_tag() for all custom query string vars,
    // wordpress will ignore them.
    add_rewrite_tag( '%wpse_thing%', '(\w+)' );
    add_rewrite_tag( '%wpse_name%', '(\w+)' );
    add_rewrite_tag( '%wpse_index%', '(\w+)' );

    // manually flushing rules so this code is easier to demo.
    // under normal circumstances you would use the plugin
    // activation hook. this will eventually call wpse_39626_rules().
add_action( 'init', 'wpse_39626_init' );

// Normally, this would get called during something like
// your plugin's activation hook. See register_activation_hook().
function wpse_39626_activate() {
    add_rewrite_rule( 'testing/(\w+)\[(\w+)\]', 'index.php?wpse_thing=custom&wpse_name=$matches[1]&wpse_index=$matches[2]', 'top' );
//register_activation_hook( __FILE__, 'wpse_39626_activate' );

// Hook into rewrite_rules_array, in case rewrite rules
// are flushed after the plugin is activated.
function wpse_39626_rules( $rules ) {
    $new_rules = array();

    // Matches: testing/outer[inner]
    //   wpse_name  = outer
    //   wpse_index = inner
    $new_rules['testing/(\w+)\[(\w+)\]'] = 'index.php?wpse_thing=custom&wpse_name=$matches[1]&wpse_index=$matches[2]';

    // prepend and return rules
    return $new_rules + $rules;
add_action( 'rewrite_rules_array', 'wpse_39626_rules' );

// Here's some demo code to intercept the page load
// and do custom functionality when our rewrite rule
// matches. (We'll just dump the matched values.)
function wpse_39626_posts( $query ) {
    if( ! is_main_query( $query ) ) {

    if( $query->get('wpse_thing') != 'custom' ) {

    var_dump( $query->get('wpse_name') );
    var_dump( $query->get('wpse_index') );

add_action( 'pre_get_posts', 'wpse_39626_posts' );

Your example is a little light on code, particularly in the URL you're trying to match (what do all those parameters correspond to?), so my answer is somewhat generic.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.