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
.
Ответы
Ответ 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 \\