面試真題:給定字符串,刪除中間的 *,保留首尾的 *。
示例:*ab**de** → *abde*
str.replaceAll("(^\\*)|(\\*$)|\\*", "$1$2");
(^\\*):捕獲組 1,匹配行首 *(\\*$):捕獲組 2,匹配行尾 *\\*:匹配任意位置的 *|:或關係,優先匹配首尾$1$2:引用捕獲組 1 和 2 的內容* 被捕獲組匹配 → 替換為自身(保留)* 被第三部分匹配 → 替換為空字符串(刪除)\\ 代表正則的 \,故 * 需寫作 \\*\1,但 replaceAll 替換字符串中必須用 $1(Perl 風格)str.replaceAll("(?
(?:負向後顧斷言,當前位置不是行首(?!$):負向前顧斷言,當前位置不是行尾*,直接替換為空效率最高,無捕獲組開銷。
// 有缺陷:尾部連續 * 會被貪婪匹配全部吃掉
str.replaceAll("(^\\*)|(\\*$)|\\*+", "$1$2");
// 修正:改為惰性匹配
str.replaceAll("(^\\*)|(\\*$)|\\*+?", "$1$2");
貪婪模式 \*+ 會匹配盡可能多的 *,導致尾部多個 * 被誤刪;加 ? 切換為惰性模式即可修復。
使用 Regex101 可視化調試、查看匹配步數。實測方案二(零寬斷言)步數最少,效率最高。