[{"data":1,"prerenderedAt":2107},["ShallowReactive",2],{"guide-regex-performance-tips":3},{"id":4,"title":5,"body":6,"date":2099,"description":2100,"extension":2101,"meta":2102,"navigation":353,"path":2103,"readingTime":1185,"seo":2104,"stem":2105,"__hash__":2106},"guides\u002Fguides\u002Fregex-performance-tips.md","Regex Performance: How to Write Fast Regular Expressions",{"type":7,"value":8,"toc":2061},"minimark",[9,14,18,21,40,44,47,52,60,76,82,132,138,183,190,196,200,203,212,218,264,278,282,285,296,300,304,320,405,409,415,474,478,542,548,616,620,623,627,642,646,653,662,679,683,686,725,729,733,784,788,816,820,849,853,882,886,1028,1032,1036,1301,1305,1332,1336,1339,1435,1439,1443,1582,1586,1732,1736,1899,1903,1906,1975,1981,1985,1988,2024,2030,2034,2057],[10,11,13],"h2",{"id":12},"why-regex-performance-matters","Why Regex Performance Matters",[15,16,17],"p",{},"Regular expressions can be deceptively simple. A regex that works perfectly on a 10-character string might take seconds — or even years — to process a 100-character string. This isn't hyperbole; poorly written regexes can exhibit exponential time complexity, causing application hangs, timeout errors, and even denial-of-service vulnerabilities (ReDoS — Regular Expression Denial of Service).",[15,19,20],{},"Understanding regex performance is crucial when:",[22,23,24,28,31,34,37],"ul",{},[25,26,27],"li",{},"Processing user input in web forms",[25,29,30],{},"Validating large documents or log files",[25,32,33],{},"Running regexes in hot loops",[25,35,36],{},"Building search functionality",[25,38,39],{},"Implementing security filters",[10,41,43],{"id":42},"the-root-cause-catastrophic-backtracking","The Root Cause: Catastrophic Backtracking",[15,45,46],{},"Most regex engines use a backtracking algorithm. When a match fails, the engine \"backs up\" and tries alternative paths. In poorly written regexes, the number of possible paths can grow exponentially.",[48,49,51],"h3",{"id":50},"a-classic-example","A Classic Example",[15,53,54,55,59],{},"Consider this regex designed to match strings wrapped in ",[56,57,58],"code",{},"\u003C >",":",[61,62,67],"pre",{"className":63,"code":64,"language":65,"meta":66,"style":66},"language-regex shiki shiki-themes github-light github-dark","\u003C.*>\n","regex","",[56,68,69],{"__ignoreMap":66},[70,71,74],"span",{"class":72,"line":73},"line",1,[70,75,64],{},[15,77,78,79,59],{},"Seems innocent, right? Let's test it against ",[56,80,81],{},"\u003Chtml>",[83,84,85,93,102,111,120,127],"ol",{},[25,86,87,90,91],{},[56,88,89],{},"\u003C"," matches ",[56,92,89],{},[25,94,95,98,99],{},[56,96,97],{},".*"," greedily matches ",[56,100,101],{},"html>",[25,103,104,107,108,110],{},[56,105,106],{},">"," tries to match ",[56,109,106],{}," but fails (already consumed)",[25,112,113,114,116,117],{},"Backtrack: ",[56,115,97],{}," gives up one character, now matches ",[56,118,119],{},"html",[25,121,122,107,124,126],{},[56,123,106],{},[56,125,106],{}," — succeeds!",[25,128,129,130],{},"Match found: ",[56,131,81],{},[15,133,134,135,59],{},"That worked fine. Now try ",[56,136,137],{},"\u003Chtml>\u003Cbody>",[83,139,140,146,153,158,161,168,175,178],{},[25,141,142,90,144],{},[56,143,89],{},[56,145,89],{},[25,147,148,98,150],{},[56,149,97],{},[56,151,152],{},"html>\u003Cbody>",[25,154,155,157],{},[56,156,106],{}," fails",[25,159,160],{},"Backtrack repeatedly...",[25,162,163,164,90,166],{},"Eventually ",[56,165,97],{},[56,167,101],{},[25,169,170,90,172,174],{},[56,171,106],{},[56,173,89],{}," — wait, no!",[25,176,177],{},"More backtracking...",[25,179,180,181],{},"Eventually matches ",[56,182,137],{},[15,184,185,186,189],{},"Still okay. But what about ",[56,187,188],{},"\u003Chtml>\u003Cbody>\u003Cdiv>","?",[15,191,192,193,195],{},"The backtracking steps grow. With nested structures, ",[56,194,97],{}," tries every possible split point.",[48,197,199],{"id":198},"the-catastrophic-case","The Catastrophic Case",[15,201,202],{},"Here's a regex that's notorious for causing ReDoS:",[61,204,206],{"className":63,"code":205,"language":65,"meta":66,"style":66},"(a+)+$\n",[56,207,208],{"__ignoreMap":66},[70,209,210],{"class":72,"line":73},[70,211,205],{},[15,213,214,215,59],{},"Testing against ",[56,216,217],{},"aaaaaaaaaaaaaaaaaaaaaaaaaaaaX",[83,219,220,230,240,252,255,258],{},[25,221,222,225,226,229],{},[56,223,224],{},"a+"," matches all the ",[56,227,228],{},"a","s",[25,231,232,233,236,237,239],{},"The outer ",[56,234,235],{},"(a+)+"," tries to capture another group — fails (no more ",[56,238,228],{},"s)",[25,241,242,243,245,246,248,249,251],{},"Backtrack: first ",[56,244,224],{}," gives up one ",[56,247,228],{},", second ",[56,250,224],{}," takes it",[25,253,254],{},"Try third group... fails",[25,256,257],{},"Backtrack more...",[25,259,260,261,263],{},"The number of permutations is 2^n where n is the number of ",[56,262,228],{},"s!",[15,265,266,270,271,273,274,277],{},[267,268,269],"strong",{},"Result:"," 30 ",[56,272,228],{},"s followed by ",[56,275,276],{},"X"," can take billions of steps.",[48,279,281],{"id":280},"visualizing-the-problem","Visualizing the Problem",[15,283,284],{},"Think of backtracking like exploring a maze:",[22,286,287,290,293],{},[25,288,289],{},"Each character is a decision point",[25,291,292],{},"The engine tries one path, then backtracks to try alternatives",[25,294,295],{},"Poor regex = exponentially many paths",[10,297,299],{"id":298},"greedy-vs-lazy-quantifiers","Greedy vs Lazy Quantifiers",[48,301,303],{"id":302},"greedy-default-behavior","Greedy (Default Behavior)",[15,305,306,307,310,311,310,314,310,316,319],{},"Greedy quantifiers (",[56,308,309],{},"*",", ",[56,312,313],{},"+",[56,315,189],{},[56,317,318],{},"{n,m}",") try to match as much as possible before backtracking.",[61,321,325],{"className":322,"code":323,"language":324,"meta":66,"style":66},"language-javascript shiki shiki-themes github-light github-dark","const text = '\u003Cdiv>Hello\u003C\u002Fdiv>\u003Cdiv>World\u003C\u002Fdiv>';\n\n\u002F\u002F Greedy: matches from first \u003C to last >\ntext.match(\u002F\u003C.*>\u002F);\n\u002F\u002F Result: '\u003Cdiv>Hello\u003C\u002Fdiv>\u003Cdiv>World\u003C\u002Fdiv>'\n\u002F\u002F Steps: \u003C.*> matches all, then backtracks to find last >\n","javascript",[56,326,327,348,355,362,393,399],{"__ignoreMap":66},[70,328,329,333,337,340,344],{"class":72,"line":73},[70,330,332],{"class":331},"szBVR","const",[70,334,336],{"class":335},"sj4cs"," text",[70,338,339],{"class":331}," =",[70,341,343],{"class":342},"sZZnC"," '\u003Cdiv>Hello\u003C\u002Fdiv>\u003Cdiv>World\u003C\u002Fdiv>'",[70,345,347],{"class":346},"sVt8B",";\n",[70,349,351],{"class":72,"line":350},2,[70,352,354],{"emptyLinePlaceholder":353},true,"\n",[70,356,358],{"class":72,"line":357},3,[70,359,361],{"class":360},"sJ8bj","\u002F\u002F Greedy: matches from first \u003C to last >\n",[70,363,365,368,372,375,378,381,384,386,388,390],{"class":72,"line":364},4,[70,366,367],{"class":346},"text.",[70,369,371],{"class":370},"sScJk","match",[70,373,374],{"class":346},"(",[70,376,377],{"class":342},"\u002F",[70,379,89],{"class":380},"sA_wV",[70,382,383],{"class":335},".",[70,385,309],{"class":331},[70,387,106],{"class":380},[70,389,377],{"class":342},[70,391,392],{"class":346},");\n",[70,394,396],{"class":72,"line":395},5,[70,397,398],{"class":360},"\u002F\u002F Result: '\u003Cdiv>Hello\u003C\u002Fdiv>\u003Cdiv>World\u003C\u002Fdiv>'\n",[70,400,402],{"class":72,"line":401},6,[70,403,404],{"class":360},"\u002F\u002F Steps: \u003C.*> matches all, then backtracks to find last >\n",[48,406,408],{"id":407},"lazy-non-greedy","Lazy (Non-Greedy)",[15,410,411,412,414],{},"Adding ",[56,413,189],{}," after a quantifier makes it lazy — match as little as possible.",[61,416,418],{"className":322,"code":417,"language":324,"meta":66,"style":66},"const text = '\u003Cdiv>Hello\u003C\u002Fdiv>\u003Cdiv>World\u003C\u002Fdiv>';\n\n\u002F\u002F Lazy: matches from first \u003C to first >\ntext.match(\u002F\u003C.*?>\u002F);\n\u002F\u002F Result: '\u003Cdiv>'\n\u002F\u002F Steps: \u003C.*?> matches minimally, then immediately tries >\n",[56,419,420,432,436,441,464,469],{"__ignoreMap":66},[70,421,422,424,426,428,430],{"class":72,"line":73},[70,423,332],{"class":331},[70,425,336],{"class":335},[70,427,339],{"class":331},[70,429,343],{"class":342},[70,431,347],{"class":346},[70,433,434],{"class":72,"line":350},[70,435,354],{"emptyLinePlaceholder":353},[70,437,438],{"class":72,"line":357},[70,439,440],{"class":360},"\u002F\u002F Lazy: matches from first \u003C to first >\n",[70,442,443,445,447,449,451,453,455,458,460,462],{"class":72,"line":364},[70,444,367],{"class":346},[70,446,371],{"class":370},[70,448,374],{"class":346},[70,450,377],{"class":342},[70,452,89],{"class":380},[70,454,383],{"class":335},[70,456,457],{"class":331},"*?",[70,459,106],{"class":380},[70,461,377],{"class":342},[70,463,392],{"class":346},[70,465,466],{"class":72,"line":395},[70,467,468],{"class":360},"\u002F\u002F Result: '\u003Cdiv>'\n",[70,470,471],{"class":72,"line":401},[70,472,473],{"class":360},"\u002F\u002F Steps: \u003C.*?> matches minimally, then immediately tries >\n",[48,475,477],{"id":476},"performance-comparison","Performance Comparison",[479,480,481,500],"table",{},[482,483,484],"thead",{},[485,486,487,491,494,497],"tr",{},[488,489,490],"th",{},"Pattern",[488,492,493],{},"Text",[488,495,496],{},"Result",[488,498,499],{},"Backtracking",[501,502,503,523],"tbody",{},[485,504,505,511,516,520],{},[506,507,508],"td",{},[56,509,510],{},"\u003C.*>",[506,512,513],{},[56,514,515],{},"\u003Ca>\u003Cb>",[506,517,518],{},[56,519,515],{},[506,521,522],{},"High (many steps)",[485,524,525,530,534,539],{},[506,526,527],{},[56,528,529],{},"\u003C.*?>",[506,531,532],{},[56,533,515],{},[506,535,536],{},[56,537,538],{},"\u003Ca>",[506,540,541],{},"Low (stops early)",[15,543,544,547],{},[267,545,546],{},"Rule of thumb:"," If you know what you're looking for (e.g., closing tag), use lazy quantifiers or be more specific.",[61,549,551],{"className":322,"code":550,"language":324,"meta":66,"style":66},"\u002F\u002F Bad: greedy catch-all\n\u002F\u003C.*>\u002F;\n\n\u002F\u002F Better: specific character class\n\u002F\u003C[^>]*>\u002F;\n\n\u002F\u002F Best: use a parser for HTML\u002FXML!\n",[56,552,553,558,574,578,583,606,610],{"__ignoreMap":66},[70,554,555],{"class":72,"line":73},[70,556,557],{"class":360},"\u002F\u002F Bad: greedy catch-all\n",[70,559,560,562,564,566,568,570,572],{"class":72,"line":350},[70,561,377],{"class":342},[70,563,89],{"class":380},[70,565,383],{"class":335},[70,567,309],{"class":331},[70,569,106],{"class":380},[70,571,377],{"class":342},[70,573,347],{"class":346},[70,575,576],{"class":72,"line":357},[70,577,354],{"emptyLinePlaceholder":353},[70,579,580],{"class":72,"line":364},[70,581,582],{"class":360},"\u002F\u002F Better: specific character class\n",[70,584,585,587,589,592,595,598,600,602,604],{"class":72,"line":395},[70,586,377],{"class":342},[70,588,89],{"class":380},[70,590,591],{"class":335},"[",[70,593,594],{"class":331},"^",[70,596,597],{"class":335},">]",[70,599,309],{"class":331},[70,601,106],{"class":380},[70,603,377],{"class":342},[70,605,347],{"class":346},[70,607,608],{"class":72,"line":401},[70,609,354],{"emptyLinePlaceholder":353},[70,611,613],{"class":72,"line":612},7,[70,614,615],{"class":360},"\u002F\u002F Best: use a parser for HTML\u002FXML!\n",[10,617,619],{"id":618},"possessive-quantifiers-and-atomic-groups","Possessive Quantifiers and Atomic Groups",[15,621,622],{},"Some regex engines (Java, PCRE, .NET) support possessive quantifiers that never backtrack.",[48,624,626],{"id":625},"possessive-quantifiers-java-pcre","Possessive Quantifiers (Java, PCRE)",[61,628,630],{"className":63,"code":629,"language":65,"meta":66,"style":66},"a++       # Possessive + (never gives up match)\n.*+       # Possessive * (never backtracks)\n",[56,631,632,637],{"__ignoreMap":66},[70,633,634],{"class":72,"line":73},[70,635,636],{},"a++       # Possessive + (never gives up match)\n",[70,638,639],{"class":72,"line":350},[70,640,641],{},".*+       # Possessive * (never backtracks)\n",[48,643,645],{"id":644},"atomic-groups-more-widely-supported","Atomic Groups (More Widely Supported)",[15,647,648,649,652],{},"Atomic groups ",[56,650,651],{},"(?>...)"," prevent backtracking into the group.",[61,654,656],{"className":63,"code":655,"language":65,"meta":66,"style":66},"(?>a+)b   # Once a+ matches, those a's are locked in\n",[56,657,658],{"__ignoreMap":66},[70,659,660],{"class":72,"line":73},[70,661,655],{},[15,663,664,667,668,671,672,675,676,678],{},[267,665,666],{},"Why this helps:"," If the ",[56,669,670],{},"b"," fails to match, the engine won't backtrack into the ",[56,673,674],{},"(?>a+)"," to try fewer ",[56,677,228],{},"s.",[48,680,682],{"id":681},"javascript-workaround","JavaScript Workaround",[15,684,685],{},"JavaScript doesn't support atomic groups natively, but you can simulate with lookaheads:",[61,687,689],{"className":322,"code":688,"language":324,"meta":66,"style":66},"\u002F\u002F Instead of (?>a+)b\n(?=(a+))\\1b\n\n\u002F\u002F The lookahead matches and captures, then \\1 references the capture\n\u002F\u002F Since lookahead doesn't consume, backtracking into it is limited\n",[56,690,691,696,711,715,720],{"__ignoreMap":66},[70,692,693],{"class":72,"line":73},[70,694,695],{"class":360},"\u002F\u002F Instead of (?>a+)b\n",[70,697,698,700,703,706,708],{"class":72,"line":350},[70,699,374],{"class":346},[70,701,702],{"class":331},"?=",[70,704,705],{"class":346},"(a",[70,707,313],{"class":331},[70,709,710],{"class":346},"))\\1b\n",[70,712,713],{"class":72,"line":357},[70,714,354],{"emptyLinePlaceholder":353},[70,716,717],{"class":72,"line":364},[70,718,719],{"class":360},"\u002F\u002F The lookahead matches and captures, then \\1 references the capture\n",[70,721,722],{"class":72,"line":395},[70,723,724],{"class":360},"\u002F\u002F Since lookahead doesn't consume, backtracking into it is limited\n",[10,726,728],{"id":727},"common-performance-traps-and-fixes","Common Performance Traps and Fixes",[48,730,732],{"id":731},"trap-1-nested-quantifiers","Trap 1: Nested Quantifiers",[61,734,736],{"className":63,"code":735,"language":65,"meta":66,"style":66},"# BAD: Catastrophic backtracking\n(a+)+\n(.*)*\n(.+)+\n\n# BETTER: Use specific counts or single quantifiers\na+\n.* \n.+\n",[56,737,738,743,748,753,758,762,767,772,778],{"__ignoreMap":66},[70,739,740],{"class":72,"line":73},[70,741,742],{},"# BAD: Catastrophic backtracking\n",[70,744,745],{"class":72,"line":350},[70,746,747],{},"(a+)+\n",[70,749,750],{"class":72,"line":357},[70,751,752],{},"(.*)*\n",[70,754,755],{"class":72,"line":364},[70,756,757],{},"(.+)+\n",[70,759,760],{"class":72,"line":395},[70,761,354],{"emptyLinePlaceholder":353},[70,763,764],{"class":72,"line":401},[70,765,766],{},"# BETTER: Use specific counts or single quantifiers\n",[70,768,769],{"class":72,"line":612},[70,770,771],{},"a+\n",[70,773,775],{"class":72,"line":774},8,[70,776,777],{},".* \n",[70,779,781],{"class":72,"line":780},9,[70,782,783],{},".+\n",[48,785,787],{"id":786},"trap-2-overly-broad-character-classes","Trap 2: Overly Broad Character Classes",[61,789,791],{"className":63,"code":790,"language":65,"meta":66,"style":66},"# BAD: .* matches too much\n\u003C.*>\n\n# BETTER: Match only what you expect\n\u003C[^>]*>\n",[56,792,793,798,802,806,811],{"__ignoreMap":66},[70,794,795],{"class":72,"line":73},[70,796,797],{},"# BAD: .* matches too much\n",[70,799,800],{"class":72,"line":350},[70,801,64],{},[70,803,804],{"class":72,"line":357},[70,805,354],{"emptyLinePlaceholder":353},[70,807,808],{"class":72,"line":364},[70,809,810],{},"# BETTER: Match only what you expect\n",[70,812,813],{"class":72,"line":395},[70,814,815],{},"\u003C[^>]*>\n",[48,817,819],{"id":818},"trap-3-alternations-with-overlapping-prefixes","Trap 3: Alternations with Overlapping Prefixes",[61,821,823],{"className":63,"code":822,"language":65,"meta":66,"style":66},"# BAD: Both alternatives start with a\n(aa|aaa)\n\n# BETTER: Factor out common prefix\na(a|aa)\n",[56,824,825,830,835,839,844],{"__ignoreMap":66},[70,826,827],{"class":72,"line":73},[70,828,829],{},"# BAD: Both alternatives start with a\n",[70,831,832],{"class":72,"line":350},[70,833,834],{},"(aa|aaa)\n",[70,836,837],{"class":72,"line":357},[70,838,354],{"emptyLinePlaceholder":353},[70,840,841],{"class":72,"line":364},[70,842,843],{},"# BETTER: Factor out common prefix\n",[70,845,846],{"class":72,"line":395},[70,847,848],{},"a(a|aa)\n",[48,850,852],{"id":851},"trap-4-backtracking-across-anchors","Trap 4: Backtracking Across Anchors",[61,854,856],{"className":63,"code":855,"language":65,"meta":66,"style":66},"# BAD: ^ and $ are checked repeatedly during backtracking\n^.*$\n\n# BETTER: More specific\n^[^\\n]*$\n",[56,857,858,863,868,872,877],{"__ignoreMap":66},[70,859,860],{"class":72,"line":73},[70,861,862],{},"# BAD: ^ and $ are checked repeatedly during backtracking\n",[70,864,865],{"class":72,"line":350},[70,866,867],{},"^.*$\n",[70,869,870],{"class":72,"line":357},[70,871,354],{"emptyLinePlaceholder":353},[70,873,874],{"class":72,"line":364},[70,875,876],{},"# BETTER: More specific\n",[70,878,879],{"class":72,"line":395},[70,880,881],{},"^[^\\n]*$\n",[48,883,885],{"id":884},"trap-5-using-regex-for-parsing-structured-data","Trap 5: Using Regex for Parsing Structured Data",[61,887,889],{"className":322,"code":888,"language":324,"meta":66,"style":66},"\u002F\u002F BAD: Trying to parse HTML\u002FXML\u002FJSON with regex\nconst html = '\u003Cdiv class=\"a\">\u003Cspan>b\u003C\u002Fspan>\u003C\u002Fdiv>';\nconst match = html.match(\u002F\u003Cdiv.*?>(.*?)\u003C\\\u002Fdiv>\u002F);\n\n\u002F\u002F BETTER: Use a proper parser\nconst parser = new DOMParser();\nconst doc = parser.parseFromString(html, 'text\u002Fhtml');\nconst div = doc.querySelector('div');\n",[56,890,891,896,910,956,960,965,983,1006],{"__ignoreMap":66},[70,892,893],{"class":72,"line":73},[70,894,895],{"class":360},"\u002F\u002F BAD: Trying to parse HTML\u002FXML\u002FJSON with regex\n",[70,897,898,900,903,905,908],{"class":72,"line":350},[70,899,332],{"class":331},[70,901,902],{"class":335}," html",[70,904,339],{"class":331},[70,906,907],{"class":342}," '\u003Cdiv class=\"a\">\u003Cspan>b\u003C\u002Fspan>\u003C\u002Fdiv>'",[70,909,347],{"class":346},[70,911,912,914,917,919,922,924,926,928,931,933,935,938,940,942,945,949,952,954],{"class":72,"line":357},[70,913,332],{"class":331},[70,915,916],{"class":335}," match",[70,918,339],{"class":331},[70,920,921],{"class":346}," html.",[70,923,371],{"class":370},[70,925,374],{"class":346},[70,927,377],{"class":342},[70,929,930],{"class":380},"\u003Cdiv",[70,932,383],{"class":335},[70,934,457],{"class":331},[70,936,937],{"class":380},">(",[70,939,383],{"class":335},[70,941,457],{"class":331},[70,943,944],{"class":380},")\u003C",[70,946,948],{"class":947},"snhLl","\\\u002F",[70,950,951],{"class":380},"div>",[70,953,377],{"class":342},[70,955,392],{"class":346},[70,957,958],{"class":72,"line":364},[70,959,354],{"emptyLinePlaceholder":353},[70,961,962],{"class":72,"line":395},[70,963,964],{"class":360},"\u002F\u002F BETTER: Use a proper parser\n",[70,966,967,969,972,974,977,980],{"class":72,"line":401},[70,968,332],{"class":331},[70,970,971],{"class":335}," parser",[70,973,339],{"class":331},[70,975,976],{"class":331}," new",[70,978,979],{"class":370}," DOMParser",[70,981,982],{"class":346},"();\n",[70,984,985,987,990,992,995,998,1001,1004],{"class":72,"line":612},[70,986,332],{"class":331},[70,988,989],{"class":335}," doc",[70,991,339],{"class":331},[70,993,994],{"class":346}," parser.",[70,996,997],{"class":370},"parseFromString",[70,999,1000],{"class":346},"(html, ",[70,1002,1003],{"class":342},"'text\u002Fhtml'",[70,1005,392],{"class":346},[70,1007,1008,1010,1013,1015,1018,1021,1023,1026],{"class":72,"line":774},[70,1009,332],{"class":331},[70,1011,1012],{"class":335}," div",[70,1014,339],{"class":331},[70,1016,1017],{"class":346}," doc.",[70,1019,1020],{"class":370},"querySelector",[70,1022,374],{"class":346},[70,1024,1025],{"class":342},"'div'",[70,1027,392],{"class":346},[10,1029,1031],{"id":1030},"benchmarking-your-regexes","Benchmarking Your Regexes",[48,1033,1035],{"id":1034},"simple-javascript-benchmark","Simple JavaScript Benchmark",[61,1037,1039],{"className":322,"code":1038,"language":324,"meta":66,"style":66},"function benchmark(regex, string, iterations = 10000) {\n  const start = performance.now();\n  for (let i = 0; i \u003C iterations; i++) {\n    regex.test(string);\n  }\n  const end = performance.now();\n  return end - start;\n}\n\n\u002F\u002F Test with a problematic string\nconst regex = \u002F(a+)+$\u002F;\nconst goodString = 'aaaaa';\nconst badString = 'aaaaaaaaaaaaaaaaX';\n\nconsole.log('Good string:', benchmark(regex, goodString), 'ms');\nconsole.log('Bad string:', benchmark(regex, badString), 'ms');\n\u002F\u002F The bad string might take WAY longer!\n",[56,1040,1041,1072,1090,1123,1134,1139,1154,1168,1173,1177,1183,1210,1225,1240,1245,1272,1295],{"__ignoreMap":66},[70,1042,1043,1046,1049,1051,1054,1056,1059,1061,1064,1066,1069],{"class":72,"line":73},[70,1044,1045],{"class":331},"function",[70,1047,1048],{"class":370}," benchmark",[70,1050,374],{"class":346},[70,1052,65],{"class":1053},"s4XuR",[70,1055,310],{"class":346},[70,1057,1058],{"class":1053},"string",[70,1060,310],{"class":346},[70,1062,1063],{"class":1053},"iterations",[70,1065,339],{"class":331},[70,1067,1068],{"class":335}," 10000",[70,1070,1071],{"class":346},") {\n",[70,1073,1074,1077,1080,1082,1085,1088],{"class":72,"line":350},[70,1075,1076],{"class":331},"  const",[70,1078,1079],{"class":335}," start",[70,1081,339],{"class":331},[70,1083,1084],{"class":346}," performance.",[70,1086,1087],{"class":370},"now",[70,1089,982],{"class":346},[70,1091,1092,1095,1098,1101,1104,1107,1110,1113,1115,1118,1121],{"class":72,"line":357},[70,1093,1094],{"class":331},"  for",[70,1096,1097],{"class":346}," (",[70,1099,1100],{"class":331},"let",[70,1102,1103],{"class":346}," i ",[70,1105,1106],{"class":331},"=",[70,1108,1109],{"class":335}," 0",[70,1111,1112],{"class":346},"; i ",[70,1114,89],{"class":331},[70,1116,1117],{"class":346}," iterations; i",[70,1119,1120],{"class":331},"++",[70,1122,1071],{"class":346},[70,1124,1125,1128,1131],{"class":72,"line":364},[70,1126,1127],{"class":346},"    regex.",[70,1129,1130],{"class":370},"test",[70,1132,1133],{"class":346},"(string);\n",[70,1135,1136],{"class":72,"line":395},[70,1137,1138],{"class":346},"  }\n",[70,1140,1141,1143,1146,1148,1150,1152],{"class":72,"line":401},[70,1142,1076],{"class":331},[70,1144,1145],{"class":335}," end",[70,1147,339],{"class":331},[70,1149,1084],{"class":346},[70,1151,1087],{"class":370},[70,1153,982],{"class":346},[70,1155,1156,1159,1162,1165],{"class":72,"line":612},[70,1157,1158],{"class":331},"  return",[70,1160,1161],{"class":346}," end ",[70,1163,1164],{"class":331},"-",[70,1166,1167],{"class":346}," start;\n",[70,1169,1170],{"class":72,"line":774},[70,1171,1172],{"class":346},"}\n",[70,1174,1175],{"class":72,"line":780},[70,1176,354],{"emptyLinePlaceholder":353},[70,1178,1180],{"class":72,"line":1179},10,[70,1181,1182],{"class":360},"\u002F\u002F Test with a problematic string\n",[70,1184,1186,1188,1191,1193,1196,1198,1200,1203,1206,1208],{"class":72,"line":1185},11,[70,1187,332],{"class":331},[70,1189,1190],{"class":335}," regex",[70,1192,339],{"class":331},[70,1194,1195],{"class":342}," \u002F",[70,1197,705],{"class":380},[70,1199,313],{"class":331},[70,1201,1202],{"class":380},")",[70,1204,1205],{"class":331},"+$",[70,1207,377],{"class":342},[70,1209,347],{"class":346},[70,1211,1213,1215,1218,1220,1223],{"class":72,"line":1212},12,[70,1214,332],{"class":331},[70,1216,1217],{"class":335}," goodString",[70,1219,339],{"class":331},[70,1221,1222],{"class":342}," 'aaaaa'",[70,1224,347],{"class":346},[70,1226,1228,1230,1233,1235,1238],{"class":72,"line":1227},13,[70,1229,332],{"class":331},[70,1231,1232],{"class":335}," badString",[70,1234,339],{"class":331},[70,1236,1237],{"class":342}," 'aaaaaaaaaaaaaaaaX'",[70,1239,347],{"class":346},[70,1241,1243],{"class":72,"line":1242},14,[70,1244,354],{"emptyLinePlaceholder":353},[70,1246,1248,1251,1254,1256,1259,1261,1264,1267,1270],{"class":72,"line":1247},15,[70,1249,1250],{"class":346},"console.",[70,1252,1253],{"class":370},"log",[70,1255,374],{"class":346},[70,1257,1258],{"class":342},"'Good string:'",[70,1260,310],{"class":346},[70,1262,1263],{"class":370},"benchmark",[70,1265,1266],{"class":346},"(regex, goodString), ",[70,1268,1269],{"class":342},"'ms'",[70,1271,392],{"class":346},[70,1273,1275,1277,1279,1281,1284,1286,1288,1291,1293],{"class":72,"line":1274},16,[70,1276,1250],{"class":346},[70,1278,1253],{"class":370},[70,1280,374],{"class":346},[70,1282,1283],{"class":342},"'Bad string:'",[70,1285,310],{"class":346},[70,1287,1263],{"class":370},[70,1289,1290],{"class":346},"(regex, badString), ",[70,1292,1269],{"class":342},[70,1294,392],{"class":346},[70,1296,1298],{"class":72,"line":1297},17,[70,1299,1300],{"class":360},"\u002F\u002F The bad string might take WAY longer!\n",[48,1302,1304],{"id":1303},"online-tools","Online Tools",[22,1306,1307,1316,1324],{},[25,1308,1309,1315],{},[228,1310,1314],{"href":1311,"rel":1312},"https:\u002F\u002Fregex101.com",[1313],"nofollow","Regex101"," — Shows regex steps and warnings",[25,1317,1318,1323],{},[228,1319,1322],{"href":1320,"rel":1321},"https:\u002F\u002Fwww.regexbuddy.com",[1313],"RegexBuddy"," — Advanced debugging",[25,1325,1326,1331],{},[228,1327,1330],{"href":1328,"rel":1329},"https:\u002F\u002Fregexr.com",[1313],"RegExr"," — Visual highlighting",[10,1333,1335],{"id":1334},"optimization-checklist","Optimization Checklist",[15,1337,1338],{},"When writing regexes, check each item:",[22,1340,1343,1362,1374,1383,1399,1408,1417,1426],{"className":1341},[1342],"contains-task-list",[25,1344,1347,1351,1352,1355,1356,1358,1359],{"className":1345},[1346],"task-list-item",[1348,1349],"input",{"disabled":353,"type":1350},"checkbox"," ",[267,1353,1354],{},"Avoid nested quantifiers"," like ",[56,1357,235],{}," or ",[56,1360,1361],{},"(.*)*",[25,1363,1365,1351,1367,1370,1371,1373],{"className":1364},[1346],[1348,1366],{"disabled":353,"type":1350},[267,1368,1369],{},"Use specific character classes"," instead of ",[56,1372,383],{}," when possible",[25,1375,1377,1351,1379,1382],{"className":1376},[1346],[1348,1378],{"disabled":353,"type":1350},[267,1380,1381],{},"Prefer lazy quantifiers"," when matching until a known delimiter",[25,1384,1386,1351,1388,1391,1392,1394,1395,1398],{"className":1385},[1346],[1348,1387],{"disabled":353,"type":1350},[267,1389,1390],{},"Anchor your patterns"," with ",[56,1393,594],{}," and ",[56,1396,1397],{},"$"," when matching full strings",[25,1400,1402,1351,1404,1407],{"className":1401},[1346],[1348,1403],{"disabled":353,"type":1350},[267,1405,1406],{},"Factor out common prefixes"," in alternations",[25,1409,1411,1351,1413,1416],{"className":1410},[1346],[1348,1412],{"disabled":353,"type":1350},[267,1414,1415],{},"Test with long, malicious strings"," to catch ReDoS",[25,1418,1420,1351,1422,1425],{"className":1419},[1346],[1348,1421],{"disabled":353,"type":1350},[267,1423,1424],{},"Consider atomic groups"," if your engine supports them",[25,1427,1429,1351,1431,1434],{"className":1428},[1346],[1348,1430],{"disabled":353,"type":1350},[267,1432,1433],{},"Don't use regex for parsing"," HTML, XML, or other nested structures",[10,1436,1438],{"id":1437},"real-world-examples","Real-World Examples",[48,1440,1442],{"id":1441},"example-1-email-validation","Example 1: Email Validation",[61,1444,1446],{"className":322,"code":1445,"language":324,"meta":66,"style":66},"\u002F\u002F BAD: Overly complex, potential backtracking\nconst badEmailRegex = \u002F^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$\u002F;\n\n\u002F\u002F GOOD: Same thing, but recognize it's already fairly optimal\n\u002F\u002F The character classes are specific, no nested quantifiers\nconst goodEmailRegex = \u002F^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$\u002F;\n\n\u002F\u002F BETTER: If you control the input, simpler might suffice\nconst simplerEmailRegex = \u002F^\\S+@\\S+\\.\\S+$\u002F;\n",[56,1447,1448,1453,1492,1496,1501,1506,1539,1543,1548],{"__ignoreMap":66},[70,1449,1450],{"class":72,"line":73},[70,1451,1452],{"class":360},"\u002F\u002F BAD: Overly complex, potential backtracking\n",[70,1454,1455,1457,1460,1462,1464,1466,1469,1471,1474,1477,1479,1482,1485,1488,1490],{"class":72,"line":350},[70,1456,332],{"class":331},[70,1458,1459],{"class":335}," badEmailRegex",[70,1461,339],{"class":331},[70,1463,1195],{"class":342},[70,1465,594],{"class":331},[70,1467,1468],{"class":335},"[a-zA-Z0-9._%+-]",[70,1470,313],{"class":331},[70,1472,1473],{"class":380},"@",[70,1475,1476],{"class":335},"[a-zA-Z0-9.-]",[70,1478,313],{"class":331},[70,1480,1481],{"class":947},"\\.",[70,1483,1484],{"class":335},"[a-zA-Z]",[70,1486,1487],{"class":331},"{2,}$",[70,1489,377],{"class":342},[70,1491,347],{"class":346},[70,1493,1494],{"class":72,"line":357},[70,1495,354],{"emptyLinePlaceholder":353},[70,1497,1498],{"class":72,"line":364},[70,1499,1500],{"class":360},"\u002F\u002F GOOD: Same thing, but recognize it's already fairly optimal\n",[70,1502,1503],{"class":72,"line":395},[70,1504,1505],{"class":360},"\u002F\u002F The character classes are specific, no nested quantifiers\n",[70,1507,1508,1510,1513,1515,1517,1519,1521,1523,1525,1527,1529,1531,1533,1535,1537],{"class":72,"line":401},[70,1509,332],{"class":331},[70,1511,1512],{"class":335}," goodEmailRegex",[70,1514,339],{"class":331},[70,1516,1195],{"class":342},[70,1518,594],{"class":331},[70,1520,1468],{"class":335},[70,1522,313],{"class":331},[70,1524,1473],{"class":380},[70,1526,1476],{"class":335},[70,1528,313],{"class":331},[70,1530,1481],{"class":947},[70,1532,1484],{"class":335},[70,1534,1487],{"class":331},[70,1536,377],{"class":342},[70,1538,347],{"class":346},[70,1540,1541],{"class":72,"line":612},[70,1542,354],{"emptyLinePlaceholder":353},[70,1544,1545],{"class":72,"line":774},[70,1546,1547],{"class":360},"\u002F\u002F BETTER: If you control the input, simpler might suffice\n",[70,1549,1550,1552,1555,1557,1559,1561,1564,1566,1568,1570,1572,1574,1576,1578,1580],{"class":72,"line":780},[70,1551,332],{"class":331},[70,1553,1554],{"class":335}," simplerEmailRegex",[70,1556,339],{"class":331},[70,1558,1195],{"class":342},[70,1560,594],{"class":331},[70,1562,1563],{"class":335},"\\S",[70,1565,313],{"class":331},[70,1567,1473],{"class":380},[70,1569,1563],{"class":335},[70,1571,313],{"class":331},[70,1573,1481],{"class":947},[70,1575,1563],{"class":335},[70,1577,1205],{"class":331},[70,1579,377],{"class":342},[70,1581,347],{"class":346},[48,1583,1585],{"id":1584},"example-2-url-path-matching","Example 2: URL Path Matching",[61,1587,1589],{"className":322,"code":1588,"language":324,"meta":66,"style":66},"\u002F\u002F BAD: Greedy catch-all\nconst badPathRegex = \u002F^\\\u002Fapi\\\u002F.*\\\u002Fdetails$\u002F;\n\n\u002F\u002F GOOD: Specific character class\nconst goodPathRegex = \u002F^\\\u002Fapi\\\u002F[^\\\u002F]+\\\u002Fdetails$\u002F;\n\n\u002F\u002F Even better: exact segment count\nconst exactPathRegex = \u002F^\\\u002Fapi\\\u002F([^\\\u002F]+)\\\u002Fdetails$\u002F;\n",[56,1590,1591,1596,1631,1635,1640,1680,1684,1689],{"__ignoreMap":66},[70,1592,1593],{"class":72,"line":73},[70,1594,1595],{"class":360},"\u002F\u002F BAD: Greedy catch-all\n",[70,1597,1598,1600,1603,1605,1607,1609,1611,1614,1616,1618,1620,1622,1625,1627,1629],{"class":72,"line":350},[70,1599,332],{"class":331},[70,1601,1602],{"class":335}," badPathRegex",[70,1604,339],{"class":331},[70,1606,1195],{"class":342},[70,1608,594],{"class":331},[70,1610,948],{"class":947},[70,1612,1613],{"class":380},"api",[70,1615,948],{"class":947},[70,1617,383],{"class":335},[70,1619,309],{"class":331},[70,1621,948],{"class":947},[70,1623,1624],{"class":380},"details",[70,1626,1397],{"class":331},[70,1628,377],{"class":342},[70,1630,347],{"class":346},[70,1632,1633],{"class":72,"line":357},[70,1634,354],{"emptyLinePlaceholder":353},[70,1636,1637],{"class":72,"line":364},[70,1638,1639],{"class":360},"\u002F\u002F GOOD: Specific character class\n",[70,1641,1642,1644,1647,1649,1651,1653,1655,1657,1659,1661,1663,1665,1668,1670,1672,1674,1676,1678],{"class":72,"line":395},[70,1643,332],{"class":331},[70,1645,1646],{"class":335}," goodPathRegex",[70,1648,339],{"class":331},[70,1650,1195],{"class":342},[70,1652,594],{"class":331},[70,1654,948],{"class":947},[70,1656,1613],{"class":380},[70,1658,948],{"class":947},[70,1660,591],{"class":335},[70,1662,594],{"class":331},[70,1664,948],{"class":947},[70,1666,1667],{"class":335},"]",[70,1669,313],{"class":331},[70,1671,948],{"class":947},[70,1673,1624],{"class":380},[70,1675,1397],{"class":331},[70,1677,377],{"class":342},[70,1679,347],{"class":346},[70,1681,1682],{"class":72,"line":401},[70,1683,354],{"emptyLinePlaceholder":353},[70,1685,1686],{"class":72,"line":612},[70,1687,1688],{"class":360},"\u002F\u002F Even better: exact segment count\n",[70,1690,1691,1693,1696,1698,1700,1702,1704,1706,1708,1710,1712,1714,1716,1718,1720,1722,1724,1726,1728,1730],{"class":72,"line":774},[70,1692,332],{"class":331},[70,1694,1695],{"class":335}," exactPathRegex",[70,1697,339],{"class":331},[70,1699,1195],{"class":342},[70,1701,594],{"class":331},[70,1703,948],{"class":947},[70,1705,1613],{"class":380},[70,1707,948],{"class":947},[70,1709,374],{"class":380},[70,1711,591],{"class":335},[70,1713,594],{"class":331},[70,1715,948],{"class":947},[70,1717,1667],{"class":335},[70,1719,313],{"class":331},[70,1721,1202],{"class":380},[70,1723,948],{"class":947},[70,1725,1624],{"class":380},[70,1727,1397],{"class":331},[70,1729,377],{"class":342},[70,1731,347],{"class":346},[48,1733,1735],{"id":1734},"example-3-log-parsing","Example 3: Log Parsing",[61,1737,1739],{"className":322,"code":1738,"language":324,"meta":66,"style":66},"\u002F\u002F BAD: Nested quantifiers\nconst badLogRegex = \u002F(\\d+:)+(.+)\u002F;\n\n\u002F\u002F GOOD: Specific format\nconst goodLogRegex = \u002F^(\\d{1,3}:)+\\s+(.+)$\u002F;\n\n\u002F\u002F BETTER: Parse known format\nconst logLine = '123:456:789 Some message';\nconst parts = logLine.split(':');\nconst message = parts.pop(); \u002F\u002F \"789 Some message\"\n",[56,1740,1741,1746,1781,1785,1790,1833,1837,1842,1856,1878],{"__ignoreMap":66},[70,1742,1743],{"class":72,"line":73},[70,1744,1745],{"class":360},"\u002F\u002F BAD: Nested quantifiers\n",[70,1747,1748,1750,1753,1755,1757,1759,1762,1764,1767,1769,1771,1773,1775,1777,1779],{"class":72,"line":350},[70,1749,332],{"class":331},[70,1751,1752],{"class":335}," badLogRegex",[70,1754,339],{"class":331},[70,1756,1195],{"class":342},[70,1758,374],{"class":380},[70,1760,1761],{"class":335},"\\d",[70,1763,313],{"class":331},[70,1765,1766],{"class":380},":)",[70,1768,313],{"class":331},[70,1770,374],{"class":380},[70,1772,383],{"class":335},[70,1774,313],{"class":331},[70,1776,1202],{"class":380},[70,1778,377],{"class":342},[70,1780,347],{"class":346},[70,1782,1783],{"class":72,"line":357},[70,1784,354],{"emptyLinePlaceholder":353},[70,1786,1787],{"class":72,"line":364},[70,1788,1789],{"class":360},"\u002F\u002F GOOD: Specific format\n",[70,1791,1792,1794,1797,1799,1801,1803,1805,1807,1810,1812,1814,1817,1819,1821,1823,1825,1827,1829,1831],{"class":72,"line":395},[70,1793,332],{"class":331},[70,1795,1796],{"class":335}," goodLogRegex",[70,1798,339],{"class":331},[70,1800,1195],{"class":342},[70,1802,594],{"class":331},[70,1804,374],{"class":380},[70,1806,1761],{"class":335},[70,1808,1809],{"class":331},"{1,3}",[70,1811,1766],{"class":380},[70,1813,313],{"class":331},[70,1815,1816],{"class":335},"\\s",[70,1818,313],{"class":331},[70,1820,374],{"class":380},[70,1822,383],{"class":335},[70,1824,313],{"class":331},[70,1826,1202],{"class":380},[70,1828,1397],{"class":331},[70,1830,377],{"class":342},[70,1832,347],{"class":346},[70,1834,1835],{"class":72,"line":401},[70,1836,354],{"emptyLinePlaceholder":353},[70,1838,1839],{"class":72,"line":612},[70,1840,1841],{"class":360},"\u002F\u002F BETTER: Parse known format\n",[70,1843,1844,1846,1849,1851,1854],{"class":72,"line":774},[70,1845,332],{"class":331},[70,1847,1848],{"class":335}," logLine",[70,1850,339],{"class":331},[70,1852,1853],{"class":342}," '123:456:789 Some message'",[70,1855,347],{"class":346},[70,1857,1858,1860,1863,1865,1868,1871,1873,1876],{"class":72,"line":780},[70,1859,332],{"class":331},[70,1861,1862],{"class":335}," parts",[70,1864,339],{"class":331},[70,1866,1867],{"class":346}," logLine.",[70,1869,1870],{"class":370},"split",[70,1872,374],{"class":346},[70,1874,1875],{"class":342},"':'",[70,1877,392],{"class":346},[70,1879,1880,1882,1885,1887,1890,1893,1896],{"class":72,"line":1179},[70,1881,332],{"class":331},[70,1883,1884],{"class":335}," message",[70,1886,339],{"class":331},[70,1888,1889],{"class":346}," parts.",[70,1891,1892],{"class":370},"pop",[70,1894,1895],{"class":346},"(); ",[70,1897,1898],{"class":360},"\u002F\u002F \"789 Some message\"\n",[10,1900,1902],{"id":1901},"understanding-your-regex-engine","Understanding Your Regex Engine",[15,1904,1905],{},"Different engines have different performance characteristics:",[479,1907,1908,1921],{},[482,1909,1910],{},[485,1911,1912,1915,1918],{},[488,1913,1914],{},"Engine",[488,1916,1917],{},"Used By",[488,1919,1920],{},"Features",[501,1922,1923,1936,1949,1962],{},[485,1924,1925,1930,1933],{},[506,1926,1927],{},[267,1928,1929],{},"RE2",[506,1931,1932],{},"Go, Rust (regex crate)",[506,1934,1935],{},"Linear time, no backtracking, no ReDoS",[485,1937,1938,1943,1946],{},[506,1939,1940],{},[267,1941,1942],{},"PCRE",[506,1944,1945],{},"PHP, Apache",[506,1947,1948],{},"Backtracking, supports atomic groups",[485,1950,1951,1956,1959],{},[506,1952,1953],{},[267,1954,1955],{},"ICU",[506,1957,1958],{},"Java (some APIs)",[506,1960,1961],{},"Backtracking with optimizations",[485,1963,1964,1969,1972],{},[506,1965,1966],{},[267,1967,1968],{},"ECMAScript",[506,1970,1971],{},"JavaScript",[506,1973,1974],{},"Backtracking, no atomic groups",[15,1976,1977,1980],{},[267,1978,1979],{},"Key insight:"," If you're using JavaScript, you're stuck with backtracking. Write your regexes accordingly!",[10,1982,1984],{"id":1983},"summary","Summary",[15,1986,1987],{},"Regex performance boils down to controlling backtracking:",[83,1989,1990,1995,2006,2012,2018],{},[25,1991,1992,1994],{},[267,1993,1354],{}," — the #1 cause of ReDoS",[25,1996,1997,2000,2001,1370,2004,1373],{},[267,1998,1999],{},"Be specific"," — use ",[56,2002,2003],{},"[^>]*",[56,2005,97],{},[25,2007,2008,2011],{},[267,2009,2010],{},"Use lazy quantifiers"," for \"match until X\" patterns",[25,2013,2014,2017],{},[267,2015,2016],{},"Benchmark with bad input"," — test with strings designed to fail",[25,2019,2020,2023],{},[267,2021,2022],{},"Know your engine"," — RE2 is safe, ECMAScript can be dangerous",[15,2025,2026,2027],{},"Remember: ",[267,2028,2029],{},"A regex that's fast on valid input might be catastrophically slow on invalid input.",[10,2031,2033],{"id":2032},"related-tools","Related Tools",[22,2035,2036,2043,2050],{},[25,2037,2038,2042],{},[228,2039,2041],{"href":2040},"\u002Ftools\u002Fregex-tester","Regex Tester"," — Test regex with real-time highlighting",[25,2044,2045,2049],{},[228,2046,2048],{"href":2047},"\u002Fguides\u002Fregex-cheat-sheet","Regex Cheat Sheet"," — Quick regex reference",[25,2051,2052,2056],{},[228,2053,2055],{"href":2054},"\u002Fguides\u002Fcommon-regex-patterns","Common Regex Patterns"," — Ready-to-use patterns",[2058,2059,2060],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sA_wV, html code.shiki .sA_wV{--shiki-default:#032F62;--shiki-dark:#DBEDFF}html pre.shiki code .snhLl, html code.shiki .snhLl{--shiki-default:#22863A;--shiki-default-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":66,"searchDepth":350,"depth":350,"links":2062},[2063,2064,2069,2074,2079,2086,2090,2091,2096,2097,2098],{"id":12,"depth":350,"text":13},{"id":42,"depth":350,"text":43,"children":2065},[2066,2067,2068],{"id":50,"depth":357,"text":51},{"id":198,"depth":357,"text":199},{"id":280,"depth":357,"text":281},{"id":298,"depth":350,"text":299,"children":2070},[2071,2072,2073],{"id":302,"depth":357,"text":303},{"id":407,"depth":357,"text":408},{"id":476,"depth":357,"text":477},{"id":618,"depth":350,"text":619,"children":2075},[2076,2077,2078],{"id":625,"depth":357,"text":626},{"id":644,"depth":357,"text":645},{"id":681,"depth":357,"text":682},{"id":727,"depth":350,"text":728,"children":2080},[2081,2082,2083,2084,2085],{"id":731,"depth":357,"text":732},{"id":786,"depth":357,"text":787},{"id":818,"depth":357,"text":819},{"id":851,"depth":357,"text":852},{"id":884,"depth":357,"text":885},{"id":1030,"depth":350,"text":1031,"children":2087},[2088,2089],{"id":1034,"depth":357,"text":1035},{"id":1303,"depth":357,"text":1304},{"id":1334,"depth":350,"text":1335},{"id":1437,"depth":350,"text":1438,"children":2092},[2093,2094,2095],{"id":1441,"depth":357,"text":1442},{"id":1584,"depth":357,"text":1585},{"id":1734,"depth":357,"text":1735},{"id":1901,"depth":350,"text":1902},{"id":1983,"depth":350,"text":1984},{"id":2032,"depth":350,"text":2033},"2026-05-26","Learn regex performance optimization: avoid catastrophic backtracking, understand greedy vs lazy quantifiers, use atomic groups for faster matching.","md",{"immutable":353},"\u002Fguides\u002Fregex-performance-tips",{"title":5,"description":2100},"guides\u002Fregex-performance-tips","bFqtGEvSysdZ2YbQTiLZHh2A5ugidLVGCryrdG8Op08",1780401324547]