2015-11-12 3 views
1

У меня есть сегмент кода, который читает строки из файла, и я хочу отфильтровать определенные строки. В принципе, я хочу отфильтровать все, что не имеет трех столбцов, разделенных табуляцией, где первый столбец является числом, а два других столбца могут содержать каждый символ, кроме табулятора и новой строки (Dos & Unix).Строки соответствия регулярному выражению Scala со специальными символами

Я уже проверил свое регулярное выражение на http://www.regexr.com/ и там он работает.

scala> val mystr = """123456\thttp://some.url/path/to/resource\t\x03U\x1D\x1F\[email protected]\xA0>\xA0<\x86:http://some.url/path/to/resource\x06\x08+\x06\x01\x05\x05\x07\x01\x01\x04C0A0?\n""" 
scala> val myreg = "^[0-9]+(\t[^\t\r\n]+){2}(\n|\r\n)$" 

scala> mystr.matches(myreg) 
res2: Boolean = false 

Я выяснил, что проблема связана с особыми символами. Например, простой пример:

scala> val tabstr = """123456\t123456""" 
scala> val tabreg = "^[0-9]+\t[0-9]+$" 
scala> tabstr.matches(tabreg) 
res3: Boolean = false 

scala> val tabstr = "123456\t123456" 
scala> val tabreg = "^[0-9]+\t[0-9]+$" 
scala> tabstr.matches(tabreg) 
res4: Boolean = true 

Кажется, я не должен использовать сырые строки для моей линии (см mystr в первом блоке кода). Но если я не использую сырая строку Scala жалуется

error: invalid escape character 

Так как я могу справиться с этим грязным входом и по-прежнему использовать регулярные выражения, чтобы отфильтровать несколько строк?

+2

Вы хотите, чтобы ваше первое регулярное выражение '^ [0-9] + (\ t [^ \ t \ r \ n] +) {2} (\ n | \ r \ n) $' работало со всеми входами? Обратите внимание, что в строком литерале строки '' \ '' на самом деле является литералом, и для его соответствия вам нужно два литерала '' \\ '' в вашем регулярном выражении. –

+0

Конечно, я хочу, чтобы он работал со всеми входами. Это идея фильтра, не так ли? Мои входы могут содержать почти все, особенно много специальных символов. Поэтому в любой колонке не допускаются только табуляция и новая строка. Чтобы понять вас правильно: для соответствия \ t в исходной строке мне понадобится \\ t в моем регулярном выражении? – flowit

+0

Вот [demo] (http://ideone.com/owuWqL), где все ваши строки сопоставлены. Чтобы совместить строку '' \ t'' в исходной строке, вам нужно использовать '' \\ t'' в регулярном выражении с строкой-литеральным выражением и для соответствия вкладке вам нужно просто '' \ t'' в любая декларация регулярных выражений. –

ответ

3

Вы используете строковые литералы. Внутри необработанных строковых литералов \ не используется для выделения последовательностей, таких как вкладка \t или новая строка \n, \n в строком литерале строки составляет всего 2 символа друг за другом.

В регулярном выражении, чтобы соответствовать буквальному \, вам нужно использовать 2 обратных слэша в регулярном выражении с регулярной литературой с исходной строкой и 4 обратных слэша в обычной строке.

Таким образом, чтобы соответствовать всем вашим материалам, вам нужно использовать следующие регулярные выражения:

val mystr = """23456\thttp://some.url/path/to/resource\t\x03U\x1D\x1F\[email protected]\xA0>\xA0<\x86:http://some.url/path/to/resource\x06\x08+\x06\x01\x05\x05\x07\x01\x01\x04C0A0?\n""" 
val myreg = """[0-9]+(?:\\t(?:(?!\\[trn]).)*){2}(?:\\r)?(?:\\n)""" 
println(mystr.matches(myreg)) // => true 
val tabstr = """123456\t123456""" 
println(tabstr.matches("""[0-9]+\\t[0-9]+""")) // => true 
val tabstr2 = "123456\t123456" 
println(tabstr2.matches("""^[0-9]+(?:\\t|\t)[0-9]+$""")) // => true 

номер захват группу не важно здесь, так как вам просто нужно проверить, если строка matches (это означает , вам даже не нужны ^ и $, так как вся строка ввода должна соответствовать), и вы все равно можете использовать группы захвата. Если позже вам нужно извлечь группы соответствия/захвата, группы, не захватывающие захват, помогут вам получить «более чистую» структуру вывода, то есть ее.

Последние два регулярных выражения достаточно просты, (?:\\t|\t) соответствует либо \ + t, либо вкладке. \t просто соответствует вкладке.

Первый имеет умеренный жадный токен (это упрощенное регулярное выражение, лучшее из которого можно использовать при разворачивании метода петли: [0-9]+(?:\\t[^\\]*(?:\\(?![trn])[^\\]*)*){2}(?:\\r)?(?:\\n)).

  • [0-9]+ - 1 или более цифры
  • (?:\\t(?:(?!\\[trn]).)*){2} - закаленный жадный маркер, 2 вхождения символьной строки \t следует любым символы новой строки, но, кроме 2-символа комбинаций \t или \r или \n.
  • (?:\\r)? - 1 или 0 вхождений \r
  • (?:\\n) - одно вхождение в буквальном комбинации \ и n.
Смежные вопросы