簡體   English   中英

如何在Scala中實現“轉義”?

[英]How to implement “unescape” in Scala?

這是我先前問題的跟進

多虧了答案,我才意識到escape函數實際上是一個帶有參數f:Char => Seq[Char]flatMap ,用於將轉義字符映射到轉義序列(請參見答案)。

現在,我想知道如何將unescape實現為反向操作以進行escape 我猜tt應該與參數f:Seq[Char] => Char flatMap相反。 是否有意義 ? 您如何建議實施unescape

我想tt應該是帶有函數f:Seq [Char] => Char的flatMap的反向版本。 是否有意義 ?

並不是的。 您的反函數f:Seq[Char] => Char"abc"上返回什么? 它應適用於任何字符序列並返回單個字符。 您可以嘗試使用PartialFunction[Seq[Char], Char]代替,但是會遇到其他問題。 您是否將其應用於輸入的每個子序列?

更通用的解決方案是將foldLeft與累加器類型一起使用,該累加器類型既包含結果的累積部分,又包含轉義序列,例如(未經測試):

def unescape(str: String) = {
  val result = str.foldLeft[(String, Option[String])](("", None)) { case ((acc, escapedAcc), c) => 
    (c, escapedAcc) match {
      case ('&', None) =>
        (acc, Some(""))
      case (_, None) =>
        (acc + c, None)
      case ('&', Some(_)) =>
        throw new IllegalArgumentException("nested escape sequences")
      case (';', Some(escapedAcc1)) => 
        (acc + unescapeMap(escapedAcc1), None)
      case (_,  Some(escapedAcc1)) =>
        (acc, Some(escapedAcc1 + c))
    }
  }

  result match {
    case (escaped, None) =>
      escaped
    case (_, Some(_)) => 
      throw new IllegalArgumentException("unfinished escape sequence")
  }
}

val unescapeMap = Map("amp" -> "&", "lt" -> "<", ...)

(對累加器使用StringBuilder效率更高,但這更容易理解。)

但是對於這種特定情況,您可以只在&上分割字符串,然后分割除第一部分外的每個部分; ,並以此方式獲取所需零件。

這似乎是 對該問題回答的后續問題該問題的后續問題是...使用scala.xml.Utility.unescape

val sb = new StringBuilder
scala.xml.Utility.unescape("amp", sb)
println(sb.toString) // prints &

或者,如果您只想取消轉義並丟棄StringBuilder實例,則:

scala.xml.Utility.unescape("amp", new StringBuilder).toString // returns "&"

這只是解析單個逃生; 您必須自己圍繞它構建整個XML字符串的解析器-公認的答案似乎提供了這一點,但是未能重新發明scala.xml.Utility或改用scala.xml

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM