Ensure that the pattern is safe for Unicode: add the “u” option.

@param   string $pattern Pattern.

@return  string
7882
public static function safePattern($pattern)
    {
        $delimiter = \mb_substr($pattern, 0, 1);
        $options = \mb_substr(
            \mb_strrchr($pattern, $delimiter, false),
            \mb_strlen($delimiter)
        );

        if (false === \strpos($options, 'u')) {
            $pattern .= 'u';
        }

        return $pattern;
    }
433624
private static function isValidRegex($pattern)
    {
        try {
            return preg_match(sprintf('~%s~', $pattern), null) !== false;
        } catch (\Exception $e) {
            return false;
        }
    }
824442
protected function & match ($pattern, & $subject) {
		// add UTF-8 modifier to pattern if subject string contains higher chars than ASCII
		if (preg_match('#[^\x20-\x7f]#', $subject)) {
			$lastHashPos = mb_strrpos($pattern, '#');
			if (mb_strpos($pattern, 'u', $lastHashPos + 1) === FALSE)
				$pattern .= 'u';
		}
		preg_match_all($pattern, $subject, $matchedValues);
		return $matchedValues;
	}
37035
public function addRaw(string $pattern): self
    {
        if (substr($pattern, 0, 2)=='./') {
            $pattern = substr($pattern, 2);
        }
        if (!in_array($pattern, $this->raws)) {
            $this->raws[] = $pattern;
        }

        return $this;
    }
1187399
public function gsub($pattern, $replacement)
    {
        $pattern = new self($pattern);

        if ($pattern->isRegexp()) {
            return new self(preg_replace($pattern, $replacement, $this));
        } else {
            return new self(str_replace($pattern, $replacement, $this));
        }
    }
1086363
public function setPath($pattern)
    {
        if (false !== strpbrk($pattern, '?<')) {
            $pattern = preg_replace_callback('#\{(\w++)(<.*?>)?(\?[^\}]*+)?\}#', function ($m) {
                if (isset($m[3][0])) {
                    $this->setDefault($m[1], '?' !== $m[3] ? substr($m[3], 1) : null);
                }
                if (isset($m[2][0])) {
                    $this->setRequirement($m[1], substr($m[2], 1, -1));
                }

                return '{'.$m[1].'}';
            }, $pattern);
        }

        // A pattern must start with a slash and must not have multiple slashes at the beginning because the
        // generated path for this route would be confused with a network path, e.g. '//domain.com/path'.
        $this->path = '/'.ltrim(trim($pattern), '/');
        $this->compiled = null;

        return $this;
    }
375024
protected function assertPattern($pattern)
    {
        if (strlen($pattern) == 0) return null;

        $pattern = '/^'. str_replace('/', '\\/', $pattern). '$/';
        if (@preg_match($pattern, null) === false) {
            throw new DefinitionException("invalid regular expression pattern");
        }

        return $pattern;
    }
773664
public function pregUnQuote(string $pattern) : string
    {
        // Fast check, because most parent pattern like 'DefaultProperties' don't need a replacement
        if (!preg_match('/[^a-z\s]/i', $pattern)) {
            return $pattern;
        }

        $origPattern = $pattern;

        // Undo the \\x replacement, that is a fix for "Der gro\xdfe BilderSauger 2.00u" user agent match
        // @source https://github.com/browscap/browscap-php
        $pattern = preg_replace(
            ['/(?<!\\\\)\\.\\*/', '/(?<!\\\\)\\./', '/(?<!\\\\)\\\\x/'],
            ['\\*', '\\?', '\\x'],
            $pattern
        );

        if (null === $pattern) {
            throw new \UnexpectedValueException(
                sprintf('an error occured while handling pattern %s', $origPattern)
            );
        }

        // Undo preg_quote
        $pattern = str_replace(
            [
                '\\\\', '\\+', '\\*', '\\?', '\\[', '\\^', '\\]', '\\$', '\\(', '\\)', '\\{', '\\}', '\\=',
                '\\!', '\\<', '\\>', '\\|', '\\:', '\\-', '\\.', '\\/',
            ],
            [
                '\\', '+', '*', '?', '[', '^', ']', '$', '(', ')', '{', '}', '=', '!', '<', '>', '|', ':',
                '-', '.', '/',
            ],
            $pattern
        );

        return $pattern;
    }
687925
public static function matchesWildcardPattern($predicateString, $pattern) {

        // Only do a fuzzy match if at least a single * character found.
        if (is_numeric(strpos($pattern, "*"))) {
            $pattern = str_replace("\\*", "(.*)", preg_quote($pattern, "/"));
            $regex = "/" . $pattern . "/";
            return preg_match($regex, $predicateString) > 0;

        } else {
            return $predicateString == $pattern;
        }

    }
333121
public function setRegexp($pattern)
    {
        $regexp = new RegularExpression();
        $regexp->setPattern($pattern);
        $this->_regexps[] = $regexp;
    }
1069467
private function preparePattern($pattern)
    {
        $delimiterPattern = '/\\\\*' . self::DELIMITER . '/';

        // The following block escapes usages of the delimiter in the pattern if it's not already escaped.
        if (preg_match_all($delimiterPattern, $pattern, $matches, PREG_OFFSET_CAPTURE)) {
            $diffOffset = 0;

            foreach ($matches[0] as $match) {
                $str = $match[0];
                $offset = $match[1] + $diffOffset;

                $escStr = (strlen($str) % 2) ? '\\' . $str : $str; // This will increase an even number of backslashes, before a forward slash, to an odd number.  I.e. '\\/' becomes '\\\/'.

                $diffOffset += strlen($escStr) - strlen($str);

                $pattern = substr_replace($pattern, $escStr, $offset, strlen($str));
            }
        }

        return self::DELIMITER . $pattern . self::DELIMITER . $this->getModifiers();
    }
1110368
protected function get_sequence( $pattern ) {
		$characters = Strings::mb_str_split( str_replace( '.', '_', $pattern ) );
		$result     = [];

		foreach ( $characters as $index => $chr ) {
			if ( ctype_digit( $chr ) ) {
				$result[] = $chr;
			} else {
				// Append '0' if this is the first character or the previous character was not a number.
				if ( ! isset( $characters[ $index - 1 ] ) || ! ctype_digit( $characters[ $index - 1 ] ) ) {
					$result[] = '0';
				}

				// Append '0' if this is the last character.
				if ( ! isset( $characters[ $index + 1 ] ) ) {
					$result[] = '0';
				}
			}
		}

		// Do some error checking.
		$count     = count( $result );
		$count_seg = mb_strlen( $this->get_segment( $pattern ) );
		$sequence  = implode( '', $result );

		if ( $count !== $count_seg + 1 ) {
			throw new \RangeException( "Invalid segment length $count for pattern $pattern (result sequence $sequence)." );
		}

		return $sequence;
	}
913746
public function addPattern($pattern)
    {
        $this->doAddPattern($this->convertPattern($pattern));
        $this->hasPattern = true;
    }
1058530
public function escapeLikePattern(string $pattern): string {
		$esc = $this->getLikeEscapeCharacter();
		return str_replace(array($esc, QueryComparator::LIKE_WILDCARD_MANY_CHARS,
				QueryComparator::LIKE_WILDCARD_ONE_CHAR),
				array($esc . $esc,  $esc . QueryComparator::LIKE_WILDCARD_MANY_CHARS, $esc .
						QueryComparator::LIKE_WILDCARD_ONE_CHAR), $pattern);
	}
1110236
static public function prepareXsdPatternForPcre($pattern)
    {
        // XML schema always implicitly anchors the entire regular expression
        // because there is no carret (^) nor dollar ($) signs.
        // see http://www.regular-expressions.info/xml.html
        $pattern = self::escapeSymbols($pattern, array('$', '^'));
        $pattern = self::pregAddDelimiter('^' . $pattern . '$');

        // XSD regexp always case-sensitive (nothing to do), dot matches white-spaces (use PCRE_DOTALL).
        $pattern .= 's';
        
        return $pattern;
    }
191643
public function getPatternRegexp($pattern)
    {
        $matcher = $pattern;
        $matcher = trim($matcher, '/');
        $cases = $this->caseSensitive ? '' : 'i';

        if (!$matcher) {
            $matcher = '|^/$|';
        } elseif ($matcher === '*') {
            $matcher = '|^.*$|' . $cases;
        } elseif ($matcher[0] == '|') {
            //正则表达式
            $matcher = $matcher . $cases;
        } else {
            //替换 *为匹配除了 /分组之外的所有内容

            /**
             * 防止路由中出现正则表达式特殊字符 例如 - : <> 这样的特殊字符
             */
            $matcher = preg_quote($matcher,'|');
            $matcher = str_replace(['\*','\:','\[','\]','\.'],['*',':','[',']','.'],$matcher);

            $matcher = str_replace(['*', '?'], ['([^\/]*)', '([^\/]?)'], $matcher);
            $slices = $this->getSlice($matcher);
            foreach ($slices as list($slice, $reg)) {
                if (strpos($slice, '[') !== false) {
                    $matcher = str_replace($slice, $reg, $matcher);
                } else {
                    $matcher = str_replace(':' . $slice, $reg, $matcher);
                }
            }
            $matcher = '|^' . $matcher . '$|' . $cases;
        }
        return $matcher;
    }
373479
private static DateTimeFormatter getSafeDateTimeFormatter(final String pattern) {
		DateTimeFormatter safeFormatter = getDateTimeFormatter(pattern);

		if (Locale.UK.equals(safeFormatter.getLocale())) {
			return safeFormatter.withLocale(Locale.ENGLISH);
		}

		return safeFormatter;
	}