diff --git a/lib/util/named-group-regexp.js b/lib/util/named-group-regexp.js
index 3eaeb78..dc7372b 100644
--- a/lib/util/named-group-regexp.js
+++ b/lib/util/named-group-regexp.js
@@ -14,7 +14,7 @@ const pattern = [
 	'[>\']',
 	// Get everything up to the end of the capture group: this is the RegExp used
 	// when matching URLs to this route, which we can use for validation purposes.
-	'([^\\)]*(\\))?)\\??',
+	'((?:[^)(]|\\((?:[^)(]|\\((?:[^)(]|\\([^)(]*\\))*\\))*\\))*)',
 	// Capture group end
 	'\\)',
 ].join( '' );
diff --git a/lib/util/split-path.js b/lib/util/split-path.js
index 42fcf3a..6d5341a 100644
--- a/lib/util/split-path.js
+++ b/lib/util/split-path.js
@@ -3,20 +3,7 @@
  */
 'use strict';
 
-const namedGroupPattern = require( './named-group-regexp' ).pattern;
-
-// Convert capture groups to non-matching groups, because all capture groups
-// are included in the resulting array when an RE is passed to `.split()`
-// (We re-use the existing named group's capture pattern instead of creating
-// a new RegExp just for this purpose)
-const patternWithoutSubgroups = namedGroupPattern
-	.replace( /([^\\])\(([^?])/g, '$1(?:$2' );
-
-// Make a new RegExp using the same pattern as one single unified capture group,
-// so the match as a whole will be preserved after `.split()`. Permit non-slash
-// characters before or after the named capture group, although those components
-// will not yield functioning setters.
-const namedGroupRE = new RegExp( '([^/]*' + patternWithoutSubgroups + '[^/]*)' );
+const namedGroupRE = require( './named-group-regexp' ).namedGroupRE;
 
 /**
  * Divide a route string up into hierarchical components by breaking it apart
@@ -29,14 +16,24 @@ const namedGroupRE = new RegExp( '([^/]*' + patternWithoutSubgroups + '[^/]*)' )
  * @param {String} pathStr A route path string to break into components
  * @returns {String[]} An array of route component strings
  */
-module.exports = pathStr => pathStr
-	// Divide a string like "/some/path/(?P<with_named_groups>)/etc" into an
+module.exports = pathStr => {
+	let parts = [pathStr];
+	// Find the named group.
+	const namedGroupMatch = pathStr.match(namedGroupRE);
+	if (namedGroupMatch) {
+		const namedGroup = namedGroupMatch[0];
+		// Split the string into the parts surrounding the named group.
+		parts = pathStr.split(namedGroup);
+		// Add the named group into the array.
+		parts.splice(1, 0, namedGroup);
+	}
+	// This divides a string like "/some/path/(?P<with_named_groups>)/etc" into an
 	// array `[ "/some/path/", "(?P<with_named_groups>)", "/etc" ]`.
-	.split( namedGroupRE )
+
 	// Then, reduce through the array of parts, splitting any non-capture-group
 	// parts on forward slashes and discarding empty strings to create the final
 	// array of path components.
-	.reduce( ( components, part ) => {
+	return parts.reduce( ( components, part ) => {
 		if ( ! part ) {
 			// Ignore empty strings parts
 			return components;
@@ -50,3 +47,4 @@ module.exports = pathStr => pathStr
 		// Split the part on / and filter out empty strings
 		return components.concat( part.split( '/' ).filter( Boolean ) );
 	}, [] );
+}