正则表达式提取指定分隔符左侧内容:解决连字符误匹配问题
Let's break down what's going wrong and fix your BigQuery SQL step by step:
Why Your Current Code Fails
The main issue is the \b (word boundary) in your regex. In regex rules, hyphens - count as non-word characters, while letters like d/e are word characters. That means the spot between - and d in Saint-Vincent-de-Paul gets treated as a word boundary. Your regex picks up that embedded de as a valid delimiter, which is why id 5 gets split incorrectly at Saint-Vincent-.
On top of that, your WHERE REGEXP_CONTAINS(...) clause filters out rows where no valid delimiter is found (like id 4), which goes against your requirement to return the original string when there's no match.
The Fixed BigQuery SQL
Here's the adjusted code that fixes both issues:
WITH t1 AS ( SELECT 1 id,'middleDEword French,de, Polynesia.' pin_senetence,'de' pin_delimiter,'middleDEword French,' expected UNION ALL SELECT 2 id, 'Saint-Vincent-de-Paul,de,usa','de','Saint-Vincent-de-Paul,' UNION ALL SELECT 3 id,'HopiDEtal-de Saint Vincent de Paul,de,usa','de','HopiDEtal-de Saint Vincent de Paul,' UNION ALL SELECT 4 id,'middleDEword French, Polynesia.' pin_senetence,'de','middleDEword French, Polynesia.' UNION ALL SELECT 5 id,'Saint-Vincent-de-Paul,usa','de','Saint-Vincent-de-Paul,usa' UNION ALL SELECT 6 id,'HopiDEtal-de Saint DE Vincent de Paul,usa','de','HopiDEtal-de Saint DE Vincent ' ) SELECT id, pin_senetence, pin_delimiter, expected, -- Grab everything before the LAST valid delimiter, or return original if no match IFNULL(REGEXP_EXTRACT(pin_senetence, CONCAT(r'(?i)^(.*)(?<![\w-])', pin_delimiter, r'(?![\w-])')), pin_senetence) AS actual, -- Check if we hit the expected result IF(IFNULL(REGEXP_EXTRACT(pin_senetence, CONCAT(r'(?i)^(.*)(?<![\w-])', pin_delimiter, r'(?![\w-])')), pin_senetence) = expected, TRUE, FALSE) AS is_correct FROM t1;
How This Fix Works
Better Delimiter Matching: We replaced
\bwith two regex assertions:(?<![\w-]): Ensures the delimiter isn't preceded by a word character or hyphen (so embeddeddein hyphenated words gets ignored).(?![\w-]): Ensures the delimiter isn't followed by a word character or hyphen.
This guarantees we only matchdewhen it's a standalone word (surrounded by commas, spaces, punctuation, or string start/end).
Handle No-Match Cases: Using
IFNULLmeans if no valid delimiter is found (like id 4 or id 5), we just return the original string instead of filtering the row out.Greedy Matching: The
(.*)in the regex is greedy, so it will capture everything up to the last occurrence of a valid delimiter—exactly what you need for your requirement to get the leftmost last delimiter.
Test Result Outcomes
- id 5: The embedded
deinSaint-Vincent-de-Paulno longer matches, so the original string is returned as expected. - id 4: No valid delimiter exists, so the original string is returned.
- ids 1,2,3,6: All still correctly match the last standalone
deand return the expected left-hand content.
内容的提问来源于stack exchange,提问作者dpl

