Scala Regex включить многострочный параметр
Я изучаю Scala, так что это, вероятно, довольно noob-irific.
Я хочу иметь многострочное регулярное выражение.
В Ruby это будет:
MY_REGEX = /com:Node/m
Мой Scala выглядит следующим образом:
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. Любые советы были высоко оценены.
Ответы
Ответ 1
Это очень распространенная проблема при первом использовании 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
}
Что бы найти первый экземпляр 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) активирует совпадение точечных (т.е. сопоставление "." С новыми строками), а. * До и после шаблона поиска гарантирует, что он будет соответствовать любой строке. Если вы хотите "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
}
Ответ 2
Просто быстрое и грязное добавление: метод .r
на 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
в коде по всему миру.;)
Ответ 3
Просто небольшое дополнение, используйте попытку использовать флаг (?m)
(Multiline) (хотя он может быть не подходит здесь), но здесь правильный способ его использования:
например. вместо
val ScriptNode = new Regex("""<com:Node>?m""")
использовать
val ScriptNode = new Regex("""(?m)<com:Node>""")
Но опять-таки флаг (? s) более подходит в этом вопросе (добавив этот ответ только потому, что заголовок "Scala Regex enable Multiline option" )