为什么SparkSQL在SQL查询中需要两个转义反斜杠?

7
当我在Spark 2.0 REPL(spark-shell)中运行以下Scala代码时,它按照我的意图运行,使用简单的正则表达式拆分字符串。
import org.apache.spark.sql.SparkSession

// Create session
val sparkSession = SparkSession.builder.master("local").getOrCreate()

// Use SparkSQL to split a string
val query = "SELECT split('What is this? A string I think', '\\\\?') AS result"
println("The query is: " + query)
val dataframe = sparkSession.sql(query)

// Show the result
dataframe.show(1, false)

给出预期的输出

+---------------------------------+
|result                           |
+---------------------------------+
|[What is this,  A string I think]|
+---------------------------------+

但是我对需要用不只一个,而是双反斜杠(这里表示为四个反斜杠,因为在Scala中不使用三引号时必须转义反斜杠)来转义文字问号感到困惑。

我确认了我的一位同事为Spark 1.5编写的非常相似的代码,只使用单个(字面意思的)反斜杠就可以正常工作。但是如果我在Spark 2.1中仅使用单个字面反斜杠,我会从JVM的正则表达式引擎中得到错误,"Dangling meta character '?' near index 0"。我知道这意味着问号没有被正确转义,但这似乎意味着反斜杠本身必须先在Scala中进行转义,然后才能在SQL中进行转义。

我猜这对于将控制字符(如换行符)插入到SQL查询本身中可能很有用。我只是困惑这是否已经从Spark 1.5更改过了?

我已经为此搜索了很多,但没有找到任何东西。要么是发生了变化,要么是我的同事的代码以一种意外的方式工作。

我还尝试了Python/pyspark,SQL也需要双反斜杠。

有人能解释一下吗?

我在Windows上运行相对简单的设置,使用Spark 2.1.0,JDK 1.8.0_111和Hadoop winutils.exe。

3个回答

5
也许是因为反斜杠是一个特殊符号,用于连接多行SQL语句。
sql_1 = spark.sql("SELECT \
    1 AS `col1`, '{0}' AS `col2`".format(var_1))

1
请勿将您的Spark 2.1行为与同事的Spark 1.5进行比较;当涉及转义字符时,它们应该有不同的表现。引用自Spark文档

自Spark 2.0以来,我们的SQL解析器中已取消了字符串文字(包括正则表达式模式)的转义。

并且

有一个SQL配置项'spark.sql.parser.escapedStringLiterals'可用于回退到Spark 1.6关于字符串文字解析的行为。

所以,请通过 spark.conf.get('spark.sql.parser.escapedStringLiterals') 检查您的设置,并基于true/false使用单/双转义字符。

0

以下是获得相同结果的几种不同方法:

三引号

spark.sql("""SELECT split('What is this? A string I think', '\\?') AS result""").show(false)

正则表达式字符转义

spark.sql("""SELECT split('What is this? A string I think', '\\Q?\\E') AS result""").show(false)

Pattern.quote

假设你的字符串在一个数据框中。
val df = Seq(
  ("What is this? A string I think")
).toDF("your_string")

你可以利用Java的正则表达式引用功能将字符串拆分如下:
import java.util.regex.Pattern
import org.apache.spark.sql.functions._

df
  .withColumn("split_string", split($"your_string", Pattern.quote("?")))
  .show(false)

这是输出结果:

+------------------------------+---------------------------------+
|your_string                   |split_string                     |
+------------------------------+---------------------------------+
|What is this? A string I think|[What is this,  A string I think]|
+------------------------------+---------------------------------+

请参阅此帖子以获取更多信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接