Scala разбивает строку на пробелы, исключая определенные разделы

#string #scala #list

#строка #scala #Список

Вопрос:

Я хочу разделить эту строку «158.106.201.22 ‘-‘ ‘-‘ [08/ Апрель/2019:15:19:48 0000] ‘ ПОЛУЧИТЬ /media/2tSodgDfwCjIMCBY8h/200w_d.gif HTTP/ 1.1’200 3293» на семь отдельных токенов, так что в итоге я получу список, подобный:

 List("158.106.201.22", "-", "-", "08/Apr/2019:15:19:48  0000]", "GET /media/2tSodgDfwCjIMCBY8h/200w_d.gif HTTP/1.1", "200", "3293"). 
  

Я попытался использовать split() метод Scala, используя пустое пространство в качестве разделителя, но в итоге я разделяю «[08 / Апрель/2019:15:19:48 0000]» и «ПОЛУЧИТЬ /media/2tSodgDfwCjIMCBY8h/200w_d.gif HTTP/1.1»
на отдельные токены, поскольку они также содержат пустое пространство, поэтому я получаю что-то вроде:

 List("158.106.201.22", "-", "-", "[08/Apr/2019:15:19:48", " 0000]", "GET", "/media/2tSodgDfwCjIMCBY8h/200w_d.gif", "HTTP/1.1", "200", "3293")
  

Каков наилучший способ сделать это?
Спасибо!

Комментарии:

1. split() позволяет вам указать регулярное выражение, которое будет использоваться для разделения, поэтому вы можете создать регулярное выражение, которое предотвратит разделение слов, которые вы не хотите разделять.

Ответ №1:

На случай, если вам не нравится сложное регулярное выражение:

 val str = "158.106.201.22 '-' '-' [08/Apr/2019:15:19:48  0000] 'GET /media/2tSodgDfwCjIMCBY8h/200w_d.gif HTTP/1.1' 200 3293"

val stage1 =  str.split("[\[\]\']")
                  .map(_.trim)
                  .filterNot(_.isEmpty)

val result = stage1.dropRight(1)    stage1.last.split(" ")

println(result.toList)

//List(158.106.201.22, -, -, 08/Apr/2019:15:19:48  0000, GET /media/2tSodgDfwCjIMCBY8h/200w_d.gif HTTP/1.1, 200, 3293)
  

Ответ №2:

Может быть, просто использовать регулярное выражение?

 val str = "158.106.201.22 '-' '-' [08/Apr/2019:15:19:48  0000] 'GET /media/2tSodgDfwCjIMCBY8h/200w_d.gif HTTP/1.1' 200 3293" 

val pattern = "([\d\.] ) ('-') ('-') (\[. \]) ('.*') (\d ) (\d )".r

val values = pattern.findAllIn(str) match {
   case matched => (1 to matched.groupCount).map(matched.group).toArray
}

values //Array("158.106.201.22", "'-'", "'-'", "[08/Apr/2019:15:19:48  0000]", "'GET /media/2tSodgDfwCjIMCBY8h/200w_d.gif HTTP/1.1'", "200", "3293")