21

我正在学习 Scala,所以这可能很菜鸟。

我想要一个多行正则表达式。

在 Ruby 中,它将是:

MY_REGEX = /com:Node/m

我的斯卡拉看起来像:

val ScriptNode =  new Regex("""<com:Node>""")

这是我的匹配功能:

def matchNode( value : String ) : Boolean = value match 
{
    case ScriptNode() => System.out.println( "found" + value ); true
    case _ => System.out.println("not found: " + value ) ; false
}

我这样称呼它:

matchNode( "<root>\n<com:Node>\n</root>" ) // doesn't work
matchNode( "<com:Node>" ) // works

我试过了:

val ScriptNode =  new Regex("""<com:Node>?m""")

而且我真的很想避免使用 java.util.regex.Pattern。非常感谢任何提示。

4

3 回答 3

44

这是第一次使用 Scala Regex 时非常常见的问题。

当您在 Scala 中使用模式匹配时,它会尝试匹配整个字符串,就像您使用“^”和“$”一样(并且没有激活多行解析,它将 \n 匹配到 ^ 和 $)。

做你想做的事情的方法是以下之一:

def matchNode( value : String ) : Boolean = 
  (ScriptNode findFirstIn value) match {    
    case Some(v) => println( "found" + v ); true    
    case None => println("not found: " + value ) ; false
  }

它将在 value 中找到 ScriptNode 的第一个实例,并将实例返回为 v (如果你想要整个字符串,只需打印值)。要不然:

val ScriptNode =  new Regex("""(?s).*<com:Node>.*""")
def matchNode( value : String ) : Boolean = 
  value match {    
    case ScriptNode() => println( "found" + value ); true    
    case _ => println("not found: " + value ) ; false
  }

这将打印所有的价值。在这个例子中,(?s) 激活了dotall 匹配(即,将“.”匹配到新行),并且搜索模式前后的.* 确保它将匹配任何字符串。如果你想要第一个例子中的“v”,你可以这样做:

val ScriptNode =  new Regex("""(?s).*(<com:Node>).*""")
def matchNode( value : String ) : Boolean = 
  value match {    
    case ScriptNode(v) => println( "found" + v ); true    
    case _ => println("not found: " + value ) ; false
  }
于 2009-07-06T20:41:51.777 回答
5

只是一个快速而肮脏的附录:.ron 方法RichString将所有字符串转换为scala.util.matching.Regex,因此您可以执行以下操作:

"""(?s)a.*b""".r replaceAllIn ( "a\nb\nc\n", "A\nB" )

那会回来的

A
B
c

我一直使用它在 scala 控制台中快速而肮脏的正则表达式脚本。

或者在这种情况下:

def matchNode( value : String ) : Boolean = {

    """(?s).*(<com:Node>).*""".r.findAllIn( text ) match {

       case ScriptNode(v) => System.out.println( "found" + v ); true    

       case _ => System.out.println("not found: " + value ) ; false
    }
}

只是我试图new在全球范围内减少代码中这个词的使用。;)

于 2009-07-10T07:37:10.330 回答
5

只是一个小补充,使用尝试使用(?m)(Multiline) 标志(虽然它可能不适合这里)但这是使用它的正确方法:

例如,而不是

val ScriptNode =  new Regex("""<com:Node>?m""")

利用

val ScriptNode =  new Regex("""(?m)<com:Node>""")

但同样 (?s) 标志更适合这个问题(添加这个答案只是因为标题是“Scala Regex enable Multiline option”)

于 2013-12-31T00:19:12.960 回答