Scala Regex启用Multiline选项

ed.*_*ed. 21 regex scala multiline

我正在学习Scala,所以这可能是非常棒的.

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

在Ruby中它将是:

MY_REGEX = /com:Node/m
Run Code Online (Sandbox Code Playgroud)

我的Scala看起来像:

val ScriptNode =  new Regex("""<com:Node>""")
Run Code Online (Sandbox Code Playgroud)

这是我的匹配功能:

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

我这样称呼它:

matchNode( "<root>\n<com:Node>\n</root>" ) // doesn't work
matchNode( "<com:Node>" ) // works
Run Code Online (Sandbox Code Playgroud)

我试过了:

val ScriptNode =  new Regex("""<com:Node>?m""")
Run Code Online (Sandbox Code Playgroud)

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

Dan*_*ral 42

首次使用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
  }
Run Code Online (Sandbox Code Playgroud)

哪个会找到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
  }
Run Code Online (Sandbox Code Playgroud)

哪个会打印所有的价值.在这个例子中,(?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
  }
Run Code Online (Sandbox Code Playgroud)

  • 像我这样浏览读者可能并不清楚,但是对于多行字符串的匹配,包含`(?s)`是关键.请参阅http://download.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html#DOTALL (22认同)
  • @Synesso你的链接现在坏了.这里是java 7等效的http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#DOTALL (4认同)

Tri*_*cek 5

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

"""(?s)a.*b""".r replaceAllIn ( "a\nb\nc\n", "A\nB" )
Run Code Online (Sandbox Code Playgroud)

那会回来

A
B
c
Run Code Online (Sandbox Code Playgroud)

我一直使用它来在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
    }
}
Run Code Online (Sandbox Code Playgroud)

只是我试图减少new全世界代码中单词的使用.;)


Era*_*dan 5

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

例如,而不是

val ScriptNode =  new Regex("""<com:Node>?m""")
Run Code Online (Sandbox Code Playgroud)

使用

val ScriptNode =  new Regex("""(?m)<com:Node>""")
Run Code Online (Sandbox Code Playgroud)

但是(?s)标志更适合这个问题(仅仅因为标题是"Scala Regex启用Multiline选项"而添加此答案)