PHP正则匹配Öffnung失效求助:仅普通字符串可正常替换
The issue with your current regex is that the lookaround assertions aren't correctly identifying whether the word "Öffnung" is inside an HTML tag. A more reliable approach is to use preg_replace_callback to explicitly skip HTML tags while replacing the target word elsewhere.
Working Code
$content = preg_replace_callback( '/(<[^>]+>|\bÖffnung\b)/s', function($matches) { // Return HTML tags unchanged if (str_starts_with($matches[0], '<')) { return $matches[0]; } // Replace standalone "Öffnung" with the link return '<a href="">Öffnung</a>'; }, $content );
How This Works
- Regex Breakdown: The regex
/(<[^>]+>|\bÖffnung\b)/smatches two types of content:<[^>]+>: Any full HTML tag (opening, closing, or self-closing) — this captures everything from<to>.\bÖffnung\b: The standalone word "Öffnung" (using word boundaries to avoid partial matches like "Öffnungszeiten").
- Callback Logic: For each match:
- If the match is an HTML tag (starts with
<), we return it exactly as it was. - If it's the word "Öffnung", we replace it with your desired link.
- If the match is an HTML tag (starts with
This approach ensures that "Öffnung" inside HTML tags (including attribute values like <a title="Öffnung">) is never replaced, while standalone instances are updated correctly.
Why Your Original Regex Failed
Your original regex uses lookarounds that don't properly check the tag context:
(?!((<.*?))): This negative lookahead checks that there's no<immediately after the current position, which doesn't prevent matches inside tags (e.g.,<div>Öffnunghas>before the word, not<).(?!(([^<>]*?)>)): This trailing lookahead checks for no non-tag characters followed by>after the word, but it doesn't account for closing tags that start with<(like</p>), so it would incorrectly allow replacement inside some tags.
Content of the question originates from Stack Exchange, question author Hữu Công Hoàng
相关产品推荐
相关产品推荐

