Подтвердить что ты не робот

Scala: Как получить экранированное представление строки?

В принципе, я бы хотел сделать:

 // in foo.scala
 val string = "this is a string\nover two lines"
 println(string)
 println(foo(string))

Сделайте это:

% scala foo.scala
this is a string
over two lines
"this is a string\nover two lines"

В основном ищет аналог ruby ​​ String#inspect или haskell show :: String -> String.

4b9b3361

Ответ 1

Этот вопрос немного устарел, но я наткнулся на него во время поиска решения самостоятельно и был недоволен другими ответами, потому что они либо небезопасны (заменив материал самостоятельно), либо требуют внешней библиотеки.

Я нашел способ получить экранированное представление строки с помощью стандартной библиотеки scala ( > 2.10.0), которая является безопасной. Он использует небольшой трюк:

Через отражение во время выполнения вы можете легко получить представление литерального строкового выражения. Дерево такого выражения возвращается как (почти) scala код при вызове метода toString. Это особенно означает, что литерал представлен таким образом, каким он был бы в коде, т.е. Экранированным и двойным кавычками.

def escape(raw: String): String = {
  import scala.reflect.runtime.universe._
  Literal(Constant(raw)).toString
}

Таким образом, функция escape приводит к желаемому кодовому представлению предоставленной исходной строки (включая окружающие двойные кавычки):

scala> "\bHallo" + '\n' + "\tWelt"
res1: String =
?Hallo
        Welt

scala> escape("\bHallo" + '\n' + "\tWelt")
res2: String = "\bHallo\n\tWelt"

Это решение, по общему признанию, злоупотребляет отражением api, но IMHO все еще более безопасно и более удобно, чем другие предлагаемые решения.

Ответ 2

Я уверен, что это не доступно в стандартных библиотеках для Scala или Java, но находится в Apache Commons Lang:

scala> import org.apache.commons.lang.StringEscapeUtils.escapeJava
import org.apache.commons.lang.StringEscapeUtils.escapeJava

scala> escapeJava("this is a string\nover two lines")
res1: java.lang.String = this is a string\nover two lines

Вы можете легко добавить кавычки к экранированной строке, если хотите, конечно.

Ответ 3

Решение scala.reflect работает нормально. Когда вы не хотите втягивать всю эту библиотеку, это то, что кажется ей под капотом (Scala 2.11):

def quote (s: String): String = "\"" + escape(s) + "\""
def escape(s: String): String = s.flatMap(escapedChar)

def escapedChar(ch: Char): String = ch match {
  case '\b' => "\\b"
  case '\t' => "\\t"
  case '\n' => "\\n"
  case '\f' => "\\f"
  case '\r' => "\\r"
  case '"'  => "\\\""
  case '\'' => "\\\'"
  case '\\' => "\\\\"
  case _    => if (ch.isControl) "\\0" + Integer.toOctalString(ch.toInt) 
               else              String.valueOf(ch)
}

val string = "\"this\" is a string\nover two lines"
println(quote(string)) // ok

Ответ 4

Если я скомпилирую их:

object s1 {
val s1 = "this is a string\nover two lines"
}

object s2 {
val s2 = """this is a string
over two lines"""
}

Я не нахожу разницы в String, поэтому я думаю: нет возможности узнать, был ли в источнике "\n".

Но, может быть, я ошибался, и вы хотели бы получить тот же результат для обоих?

 "\"" + s.replaceAll ("\\n", "\\\\n").replaceAll ("\\t", "\\\\t") + "\""

Вторая возможность:

val mask = Array.fill (3)('"').mkString 
mask + s + mask

res5: java.lang.String = 
"""a
b"""

Тест:

scala> val s = "a\n\tb"
s: java.lang.String = 
a
    b

scala>     "\"" + s.replaceAll ("\\n", "\\\\n").replaceAll ("\\t", "\\\\t") + "\""
res7: java.lang.String = "a\n\tb"

scala> mask + s + mask
res8: java.lang.String = 
"""a
    b"""

Ответ 5

Вы можете легко создать свою собственную функцию, если вы не хотите использовать библиотеку apache:

scala> var str = "this is a string\b with some \n escapes \t so we can \r \f \' \" see how they work \\";
str: java.lang.String = 
this is a string? with some 
escapes      so we can 
' " see how they work \

scala> print(str.replace("\\","\\\\").replace("\n","\\n").replace("\b","\\b").replace("\r","\\r").replace("\t","\\t").replace("\'","\\'").replace("\f","\\f").replace("\"","\\\""));
this is a string\b with some \n escapes \t so we can \r \f \' \" see how they work \\