Использование регулярных выражений в файле для извлечения данных.Возникли проблемы с многострочным - PullRequest
2 голосов
/ 16 апреля 2019

Я ищу, чтобы перейти к следующей строке данных в текстовом файле. Вот пример данных из файла, с которым я работаю.

0519 ABF   244  AN        A1  ADV STUFF    1.0  2.0 Somestuff 018 0155  MTWTh      10:30A 11:30A    20     20     0  6.7                                                           
Somestuff 011 0145  MTWTh      12:30P  1:30P

Я пытался перейти к следующей строке, используя различные коды, такие как ... возврат каретки \ n, используя \ s + для замены большого пробела после 6.7. используя m вот так // m пока не находит результата.

Вот пример кода

while !regex_file.eof?
line = regex_file.gets.chomp
if line =~ ^.*?\d{4}\s+[A-Z]+\s+\d{3}.+$
puts line
  end
end

Использование https://rubular.com/ этот конкретный набор кода соответствует желаемому выводу для первой строки

0519 ABF   244  AN        A1  ADV STUFF    1.0  2.0 Somestuff 018 0155  MTWTh      10:30A 11:30A    20     20     0  6.7

но не соответствует и не выяснил, как найти следующую строку.

Somestuff 011 0145  MTWTh      12:30P  1:30P

Ответы [ 3 ]

1 голос
/ 16 апреля 2019

Попробуйте что-то вроде этого: \n захватывает новую строку, и вы можете применять свои собственные правила для захвата всего, что вы хотите, после \n - см. Ниже, пожалуйста:

^.*\d{4}\s+[A-Z]+\s+\d{3}.+\n.*$
1 голос
/ 16 апреля 2019

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

Вот регулярное выражение (не проверено) для сопоставления обеих строк,Обратите внимание, что вам не нужно ^.*? в начале регулярного выражения, а для части регулярного выражения, соответствующей первой строке .+$, ничего не добавляется, поэтому я удалил ее.В конце концов, вы просто сопоставляете каждую строку отдельно (line) и отображаете всю строку, если есть совпадение.Кроме того, привязка конца строки \z является более подходящей, чем привязка конца строки ($), хотя может использоваться любая из них.

r = /
    (?:             # begin non-capture group   
      \d{4}         # match 4 digits
      \s+           # match > 0 whitespaces
      [A-Z]+        # match > 0 uppercase letters
      \s+           # match > 0 whitespaces
      \d{3}         # match 3 digits
    |               # or
      \b            # match a (zero-width) word break
      [A-Z]         # match 1 uppercase letter
      [a-z]*        # match >= 0 lowercase letter
      \s+           # match > 0 whitespaces
      \d{3}         # match 3 digits
      \s+           # match > 0 whitespaces
      \d{4}         # match 4 digits
      \s+           # match > 0 whitespaces
      [A-Za-z]+     # match > 0 letters
      (?:           # begin non-capture group
        \s+         # match > 0 whitespaces
        (?:         # begin a non-capture group
          0\d       # match 0 followed by any digit
        |           # or
          1[012]    # match 1 followed by 0, 1 or 2
        )           # end non-capture group
        :           # match a colon
        [0-5][0-9]  # match 0-5 followed by 0-9     
      ){2}          # end non-capture group and execute twice
    )               # end non-capture group  
    /x              # free-spacing regex definition mode

Это регулярное выражение традиционнозаписан следующим образом.

r = /(?:\d{4}\s+[A-Z]+\s+\d{3}|\b[A-Z][a-z]*\s+\d{3}\s+\d{4}\s+[A-Za-z]+(?:\s+(?:0\d|1[012]):[0-5][0-9]){2})/

Вы можете просмотреть файл puts с соответствующими строками следующим образом:

File.foreach(fname) { |line| puts line if line.match? r }

См. IO :: foreach , которыйэто очень удобный метод для чтения файлов построчно.Примечание. Методы класса IO (например, foreach) обычно вызываются с File в качестве получателя.Это нормально, так как File.superclass #=> IO, поэтому File наследует эти методы от IO.

При использовании без блока foreach возвращает перечислитель, что также часто удобно.Если, например, вы хотите вернуть массив совпадающих строк (а не puts их), вы можете написать:

File.foreach(fname).with_object([]) do |line, arr|
  arr << line.chomp if line.match? r
end
1 голос
/ 16 апреля 2019

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

^.*?\d{4}\s+[A-Z]+\s+\d{3}.+$

соответствует в следующем порядке:

  • начало строки (^)
  • ноль или более символовнежадные .*?
  • четыре цифры (\d{4})
  • один или несколько пробелов (\s+)
  • одна или несколько заглавных букв ([A-Z]+)
  • один или несколько пробелов
  • три цифры (\d{3})
  • один или несколько символов (.+)
  • конец строки ($)

Вторая строка вашего файла:

Somestuff 011 0145  MTWTh      12:30P  1:30P

начинает совпадение 0145 MTWT, но затем не соответствует \d{3}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...