У меня есть много больших файлов TSV, которые я обрабатываю с помощью Apache Spark. Эти файлы имеют символы новой строки как разделители записей, но каждые несколько тысяч записей, некоторые escape-последовательности новой строки, предшествующие \, добавляются в колонку.Использование отрицательного lookbehind regex в качестве разделителя записей для чтения файла Hadoop в Spark
Вот пример набора данных
a b c
a b c
a b c
a b c
a b c
a b c\
\ \ \
\ \ d
a b c
a b c
Всякий раз, когда новая строка предшествует \, это означает, что это не конец записи и продолжать, пока она не попадает в символ новой строки без. Я использую отрицательное утверждение lookbehind, чтобы выбрать экранированную строку как одну запись и оставшиеся строки в качестве записи.
a b c\
\ \ \
\ \ d
Вот мой код
import org.apache.hadoop.io.LongWritable
import org.apache.hadoop.io.Text
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat
val LINE_DELIMITER = "(?<!\\\\)\n"
@transient val conf = new Configuration
conf.set("textinputformat.record.delimiter", LINE_DELIMITER)
val raw_file = sc.newAPIHadoopFile(path, classOf[TextInputFormat], classOf[LongWritable], classOf[Text], conf).map(_._2.toString)
Вместо того, чтобы 8 записей, я получаю всю строку. Вот вывод на консоль
scala> raw_file.collect
res12: Array[String] =
Array(a b c
a b c
a b c
a b c
a b c
a b c\
\ \ \
\ \ d
a b c
a b c)
Если взять эту строку и разделить его с линией Разделитель определено выше, я получаю массив из 8 строк. Таким образом, похоже, что проблема не связана с самим регулярным выражением. Фактический набор данных - это 500 + столбцов, каждый 4-5G-файл, поэтому использование целыхTextFiles и использование split later не является опцией.
Есть ли разница между тем, как regex применяется в функции split по сравнению с тем, как данные считываются в newAPIHadoopFile? Должен ли я использовать другое регулярное выражение? Или использовать какой-то другой механизм для этого?