如何在Spark(使用Scala)中用逗号替换空白?

时间:2018-11-26 20:51:23

标签: scala apache-spark apache-spark-sql databricks

我有一个这样的日志文件。我想在Scala中创建一个DataFrame。

2015-05-13T23:39:43.945958Z my-loadbalancer 192.168.131.39:2817 10.0.0.1:80 0.000086 0.001048 0.001337 200 200 0 57 "GET https://www.example.com:443/ HTTP/1.1" "curl/7.38.0" DHE-RSA-AES128-SHA TLSv1.2

我想用逗号替换所有空格,以便可以使用spark.sql,但无法这样做。

这是我尝试过的一切:

  1. 尝试首先将其作为文本文件导入,以查看是否存在replaceAll方法。
  2. 尝试根据空间拆分。

任何建议。我浏览了文档,没有像Pandas那样提到过替换功能。

3 个答案:

答案 0 :(得分:1)

您可以简单地告诉spark您的定界符是这样的空白:

class PreferenceTool<T>(private val context: Context, private val name: String,  private val default: T) {

    private val prefs: SharedPreferences by lazy {      
        context.defaultSharedPreferences     
    }

    operator fun getValue(thisRef: Any?, property: KProperty<*>): T = findPreference(name, default)

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        putPreference(name, value)
    }

    @Suppress("UNCHECKED_CAST")
    private fun findPreference(name: String, default: T): T = with(prefs) {
        val res: Any = when (default) {
            is Long -> getLong(name, default)
            is String -> getString(name, default)
            is Int -> getInt(name, default)
            is Boolean -> getBoolean(name, default)
            is Float -> getFloat(name, default)
            else -> throw IllegalArgumentException("This type can be saved into Preferences")
        }

        res as T
    }

    @SuppressLint("CommitPrefEdits")
    private fun putPreference(name: String, value: T) = with(prefs.edit()) {
        when (value) {
            is Long -> putLong(name, value)
            is String -> putString(name, value)
            is Int -> putInt(name, value)
            is Boolean -> putBoolean(name, value)
            is Float -> putFloat(name, value)
            else -> throw IllegalArgumentException("This type can't be saved into Preferences")
        }.apply()
    }
}

答案 1 :(得分:0)

由于您尚未输入列,因此我将以RDD开头,使用地图拆分文本,然后使用模式转换为Dataframe。 大概是:

val rdd = sc.textFile({logline path}).map(line=>line.split("\\s+"))

然后,您需要将RDD(每个记录是令牌数组)转换为Dataframe。最可靠的方法是将数组映射到Row对象,因为RDD [Row]是数据框的基础。

一种更简单的起床方式

spark.createDataFrame(rdd).toDF("datetime", "host", "ip", ...)

答案 2 :(得分:0)

如果您只想在空间上分开并将字符串保留在双引号中,则可以使用apache.commons.csv库。

import org.apache.commons.csv.CSVParser._
val str = """2015-05-13T23:39:43.945958Z my-loadbalancer 192.168.131.39:2817 10.0.0.1:80 0.000086 0.001048 0.001337 200 200 0 57 "GET https://www.example.com:443/ HTTP/1.1" "curl/7.38.0" DHE-RSA-AES128-SHA TLSv1.2"""
val http = csv.CSVParser.parse(str,CSVFormat.newFormat(' ').withQuote('"')).getRecords.get(0).get(11)
val curl = csv.CSVParser.parse(str,CSVFormat.newFormat(' ').withQuote('"')).getRecords.get(0).get(12)
println(http)
println(curl)

结果:

GET https://www.example.com:443/ HTTP/1.1
curl/7.38.0