2009-07-06 6 views
20

Я изучаю Scala, так что это, вероятно, довольно noob-irific.Scala Regex enable Multiline option

Я хочу иметь многострочное регулярное выражение.

В 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. Любые советы очень ценятся.

+0

приветствия для форматирования! не работает для меня –

+1

Вы должны оставить пустую строку над и под каждым кодовым блоком. –

ответ

36

Это очень распространенная проблема при первом использовании 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 
    } 

Что бы найти найти первый экземпляр скрипта-внутри значения и возврат что экземпляра, как против (если вы хотите целая строка, просто значение печати). Или еще:

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 
    } 
+1

Прекрасный материал. Ура! –

+21

Возможно, для skim-reader, как я, может быть неясно, но включение '(? S)' здесь имеет ключевое значение для сопоставления с многострочными строками. См. Http://download.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html#DOTALL – Synesso

+4

@Synesso Ваша ссылка сейчас не работает. вот эквивалент java 7 http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#DOTALL – harschware

5

Просто быстрое и грязное Приложение: .r метода на RichString преобразует все строки в scala.util.matching.Regex, так что вы можете сделать что-то вроде этого:

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

и вернется

A 
B 
c 

Я использую все это время для быстрых и грязных регулярных выражений-сценариев в коне лестницы единственный.

Или в этом случае:

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 позволит Multiline вариант")