Tableau 正则表达式实战:从混合字符串里精准拆出「年.月」
标签:Tableau · 正则表达式 · 数据清洗
一列 Metrics 里塞着 25.1U、26.5PK2、25.1Q 这种「时间+业务后缀」的混合值。本文用这个真实案例,讲清 Tableau 正则的应用场景、REGEXP_EXTRACT 语法与那个最容易踩的「捕获组」坑,最后给一张正则函数速查表。
一、什么时候该请正则出手
在 Tableau 里做数据清洗,LEFT、MID、SPLIT、CONTAINS 能解决很多问题——前提是分隔符固定、位置固定。可现实里的字段常常不讲规矩:
- 位置不固定:
25.1U是 4 个字符,25.10PK2是 7 个字符,LEFT([Metrics], 4)立刻失效。 - 格式有规律但不整齐:月份可能是 1 位(
25.9)也可能 2 位(25.10),后缀可能是字母、字母+数字,甚至没有。 - 要按「模式」而非「符号」提取:你想要的是"两位数字 + 点 + 一到两位数字"这种*结构*,而不是"第几个逗号之前"。
这正是正则表达式的主场:用一套模式描述"长什么样",让引擎去字符串里找符合这个样子的片段。一句 REGEXP_EXTRACT 就能替代一长串嵌套的 IF / LEFT / FIND。
先记一个前提: Tableau 数据提取(Extract)使用的正则引擎是 ICU(International Components for Unicode),不是 PCRE 也不是 RE2。它支持\d、{n,m}、^、.、()等常用语法,本文用到的写法都在其支持范围内。
二、案例:这列数据长什么样
字段 Metrics 的值形如下面这样。规律是:最左侧永远是「两位年度 + 点 + 一到两位月份(或季度)」,后面跟着长度不定的业务后缀。
25.1U→ 时间25.1,后缀U(1 位月份 + 单字母后缀)25.10PK2→ 时间25.10,后缀PK2(2 位月份 + 混合后缀)25.9→ 时间25.9,后缀 空(纯时间,无后缀)25.1Q→ 时间25.1,后缀Q(季度标记)26.12ABC→ 时间26.12,后缀ABC(2 位月份 + 字母后缀)
目标很明确:建一个计算字段取出左侧时间,再建一个字段取出剩余后缀。
三、REGEXP_EXTRACT 语法逐段拆解
最终能用的公式是这一句:
REGEXP_EXTRACT([Metrics], '^(\d{2}\.\d{1,2})')看着一串符号很唬人,其实把它切成几段,每段只负责一件事。下图把模式和 25.1U 一一对上:
为什么括号 ( ) 不能省
这是本案例最关键、也最反直觉的一点。翻开 Tableau 官方文档,REGEXP_EXTRACT 的示例是:
REGEXP_EXTRACT('abc 123', '[a-z]+\s+(\d+)') = '123'注意——模式匹配到的是 abc 123 整段,但函数返回的却是 123,也就是括号里那个捕获组的内容。这说明 Tableau(ICU 引擎)的 REGEXP_EXTRACT 在有捕获组时,返回的是第一个捕获组,而不是整段匹配。
踩坑记录: 如果你写成没有括号的'^\d{2}\.\d{1,2}',字段很可能返回整段或 NULL,界面上表现为「公式没反应」。把要提取的部分用()包起来,问题即解。
顺带兼容季度:25.1Q / 26.2Q
好消息是,现有公式对季度值已经天然兼容——Q 只是月份数字后面的尾巴,不在 \d{1,2} 里,会被自动丢下:25.1Q → 25.1。若你希望结果里保留 Q 标记(后续好区分季度和月份),在月份后加一个可选的 Q?(出现 0 或 1 次):
REGEXP_EXTRACT([Metrics], '^(\d{2}\.\d{1,2}Q?)') → 25.1Q
四、衍生字段:把左侧时间「减掉」,留下后缀
提取了时间,还想要剩下的业务后缀(25.1U 里的 U)。思路是反过来:用 REGEXP_REPLACE 把左侧那段时间替换成空字符串,剩下的自然就是后缀。
REGEXP_REPLACE([Metrics], '^\d{2}\.\d{1,2}', '')
几个实用变体:
- 顺带去掉空白(如
25.1 U→U而非U):
TRIM(REGEXP_REPLACE([Metrics], '^\d{2}\.\d{1,2}\s*', ''))
- 直接和提取字段相减(保证两字段永远互补):
REPLACE([Metrics], [提取时间字段], '')
注意区别:REGEXP_REPLACE是把整段匹配换掉,不依赖捕获组;只有REGEXP_EXTRACT才靠捕获组返回内容。所以这里不用加括号。
五、Tableau 正则函数速查
Tableau 的 REGEXP 家族一共四个成员,覆盖「判断 / 提取 / 多组提取 / 替换」四类需求:
REGEXP_MATCH(str, pat)—— 判断是否匹配;返回 布尔。示例REGEXP_MATCH('abc123','\d+')=trueREGEXP_EXTRACT(str, pat)—— 提取第一个捕获组;返回 字符串。示例REGEXP_EXTRACT('abc 123','[a-z]+\s+(\d+)')='123'REGEXP_EXTRACT_NTH(str, pat, n)—— 提取第 n 个捕获组(0=整段);返回 字符串。示例REGEXP_EXTRACT_NTH('abc 123','([a-z]+)\s+(\d+)',2)='123'REGEXP_REPLACE(str, pat, rep)—— 把匹配部分替换掉;返回 字符串。示例REGEXP_REPLACE('abc 123','\s','-')='abc-123'
选择逻辑很简单:
- 只想知道「有没有」→
REGEXP_MATCH(常用在IF条件里)。 - 取一段 →
REGEXP_EXTRACT(记得加捕获组)。 - 一次要取多段(如同时拿年度和月份)→
REGEXP_EXTRACT_NTH,用index指定第几组。 - 删除 / 替换 / 归一化 →
REGEXP_REPLACE。
两个通用注意点: ① 在数据提取(Extract)中,正则的 pattern 必须是常量,不能是字段。② 引擎是 ICU,遇到不确定的语法,以数据源自身文档为准;跨数据源迁移公式时留意方言差异。
六、总结
回到这个案例,两个计算字段就搞定了一列脏数据:
// 时间字段
REGEXP_EXTRACT([Metrics], '^(\d{2}\.\d{1,2})')
// 后缀字段
REGEXP_REPLACE([Metrics], '^\d{2}\.\d{1,2}', '')三条最值得记住的经验:
- 用结构描述数据:位置不固定、但有规律的字段,正则比
LEFT/MID稳得多。 - EXTRACT 一定加捕获组:Tableau 返回的是第一个
()内容,省略括号是「公式没生效」的头号原因。 - 提取与替换是一对:
EXTRACT拿走想要的,REPLACE删掉相同部分留下其余,两者天然互补。
把「长什么样」翻译成一行模式,剩下的交给引擎——这就是正则在数据清洗里最省力的用法。
结语
正则表达式在 Tableau 中的价值,不在于写多复杂的模式——而在于知道什么时候该用它。REGEXP_EXTRACT 和 REGEXP_REPLACE 能解决 90% 的文本清洗需求。
No comments yet