2016-06-05 2 views
1

У меня есть два экстрактора регулярных выражений.Scala RegEx String экстракторы ведут себя непоследовательно

Один для .java файлов, а другой для .scala файлов

val JavaFileRegEx = 
    """\S* 
    \s+ 
    // 
    \s{1} 
    ([^\.java]+) 
    \.java 
    """.replaceAll("(\\s)", "").r 

val ScalaFileRegEx = 
    """\S* 
    \s+ 
    // 
    \s{1} 
    ([^\.scala]+) 
    \.scala 
    """.replaceAll("(\\s)", "").r 

Я хочу использовать эти экстракторы выше, чтобы извлечь имя файла Java и имя файла из Scala в примере кода ниже.

val string1 = " // Tester.java" 
val string2 = " // Hello.scala" 

string1 match { 
    case JavaFileRegEx(fileName1) => println(" Java file: " + fileName1) 
    case other => println(other + "--NO_MATCH") 
} 
string2 match { 
    case ScalaFileRegEx(fileName2) => println(" Scala file: " + fileName2) 
    case other => println(other + "--NO_MATCH") 
} 

Я получаю этот вывод, указывая, что файл .java соответствует, но файл .scala этого не сделал.

Java file: Tester 
// Hello.scala--NO_MATCH 

Как выглядит файл Java, а файл .scala - нет?

+0

ваше использование класса символов неправильно в '[^ \. Scala] и' [^ \. Java] 'и – rock321987

+0

@ rock321987 - Я смущен символом «^». Я думал, что '[^ \. Java]' означало "соответствовать всем до тех пор, пока .java" –

+0

означает, что это не соответствует ** символу ** в этом наборе: '/\|/.|s|c|a|l | a'. hello содержит «l», поэтому он не соответствует. Я рекомендую вам просто использовать '\ w' вместо классов символов. Если '.' может быть частью имени файла, а затем использовать '[\ w.]'. Остальное регулярное выражение ('/ .scala') все равно должно совпадать. Вы также можете использовать '?', Чтобы быть уверенным. – micsthepick

ответ

1

ПРИМЕЧАНИЕ

[] обозначает класс символов. Он соответствует только одному символу.

[^] означает соответствие ничего, кроме в символов, присутствующий в классе символов.

В своем первом регулярном выражении

\S*\s+//\s{1}([^\.java]+)\.java 

\S* не совпадает ни с чем, как есть пространство, начиная

\s+ соответствует пространство, которое в стартовом

// матчи // буквально

\s{1} матчи следующего пространства

Вы используете [^\.java], который говорит матч ничего, кроме. или j или a или v или a, которые можно записать в виде [^.jav].

Итак, левая строка теперь быть испытываемый

Tester.java 

(Un), к счастью, любой символ из Tester не соответствует . или j или a или v, пока мы не столкнулись с .. Таким образом, Tester соответствует, а затем java также соответствует.

В вашем втором регулярного выражения

\S*\s+//\s{1}([^\.scala]+)\.scala 

\S* не совпадает ни с чем, как есть пространство, начиная

\s+ соответствует пространству, которое в стартовом

// матчей // буквально

\s{1} соответствует следующему пространству

Теперь вы используете [^\.scala], который говорит, что матч ничего кроме. или s или c или a или l или a, которые могут быть записаны в виде [^.scla].

Вы сейчас

Hello.scala 

, но (не) счастью Hello здесь содержит l, что не разрешено в соответствии с классом символов и регулярное выражение не удается.

Как исправить ошибку?

я изменить только немного вашего регулярного выражения

\S*\s+//\s{1}([^.]*)\.java 
       <--> 
    This says that match anything except . 
    You can also use \w here instead if [^.] 

Regex Demo

\S*\s+//\s{1}([^.]*)\.scala 

Regex Demo

Там нет необходимости {1} в \s{1}. Вы можете просто написать его как \s и он будет соответствовать ровно один пробел как

\S*\s+//\s([^.]*)\.java 
Смежные вопросы