Подтвердить что ты не робот

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. Любые советы были высоко оценены.

4b9b3361

Ответ 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" )