如何编写regex提取key-value字符串的value并通过Spark解析为表格?
正则修正方案
你之前写的正则无法生效主要有两个问题:
- 固定写死了键名
key,无法匹配key1等其他键 - 分支逻辑没有预留键名的通配位置,无法同时适配不同键的提取需求
可用正则
通用全匹配正则(一次提取所有键值对)
(\w+)=(".*?"|[^ ]+)
- 分组1为匹配到的键名(比如key、key1)
- 分组2为对应的值,带引号的场景会保留引号,后续可以用字符串替换去掉首尾引号即可
单独提取指定键值的正则
如果你需要单独提取某个key的value,把正则里的<键名>替换为实际键即可:
(?<=\b<键名>=)(?:"([^"]+)"|([^ ]+))
比如提取key的value用(?<=\bkey=)(?:"([^"]+)"|([^ ]+)),捕获组1/2会直接返回不带引号的1234;提取key1的value替换为key1即可得到value in text。
Spark 实现方案
我们可以用Spark的正则提取函数+集合转换函数直接解析得到目标表格,以下是Scala API的实现示例(Spark 3.1及以上版本适用):
import org.apache.spark.sql.functions._ // 样例数据,你可以替换为自己的数据源 val rawDf = Seq("key=1234 key1=\"value in text\"").toDF("raw_content") val resultDf = rawDf // 提取所有key=xxx格式的匹配项 .withColumn("kv_items", regexp_extract_all(col("raw_content"), lit("(\\w+)=(\"(.*?)\"|[^ ]+)"), 0)) // 将匹配项转换为键值对map,同时去掉值首尾的引号 .withColumn("kv_map", map_from_entries( expr("transform(kv_items, item -> struct(split(item, '=')[0] as key, regexp_replace(split(item, '=', 2)[1], '^\"|\"$', '') as value))") )) // 从map中提取目标列 .select( col("kv_map.key").alias("key"), col("kv_map.key1").alias("key1") ) // 查看结果 resultDf.show()
执行后输出结果如下:
+----+--------------+ | key| key1| +----+--------------+ |1234|value in text| +----+--------------+
如果你用Spark SQL,也可以用同样的逻辑写SQL语句实现。
内容的提问来源于stack exchange,提问作者Anu Radha
相关产品推荐
相关产品推荐

