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

Поиск строк в текстовом файле, соответствующем регулярному выражению

Может кто-нибудь объяснить, как я могу использовать регулярные выражения в Ruby, чтобы возвращать совпадения строки.

Например, если код читается в TXT файле с серией имен в нем:

John Smith
James Jones
David Brown
Tom Davidson
etc etc

.. и слово to match вводится как "ohn", оно просто возвращает "John Smith", но ни одно из других имен.

4b9b3361

Ответ 1

Вот несколько способов получить, куда вы направляетесь.

Прежде всего, я использую более идиоматический способ написания кода для чтения строк из файла. Библиотеки Ruby IO и File упрощают открытие, чтение и закрытие файла в красивом аккуратном пакете.

File.each_line('file.txt') do |li|
  puts li if (li['ohn'])
end

Это ищет "ohn" в любом месте строки, но не требует регулярного выражения.

File.each_line('file.txt') do |li|
  puts li if (li[/ohn/])
end

Это ищет ту же строку, только для этого используется регулярное выражение. Функционально это то же, что и в первом примере.

File.each_line('file.txt') do |li|
  puts li if (li[/ohn\b/])
end

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

Кроме того, при чтении файлов важно всегда думать о том, может ли прочитанный файл превышать RAM, доступное вашему приложению. Легко прочитать весь файл в памяти за один проход, а затем обработать его из ОЗУ, но вы можете повредить или убить свое приложение или машину, если вы превысите доступную вам физическую память.


Знаете ли вы, что код, показанный другими ответами, фактически загружает весь файл в ОЗУ или каким-то образом оптимизирован путем потоковой передачи из функции readlines в функцию выбора?

Из IO#readlines документация:

Считывает весь файл, указанный по имени как отдельные строки, и возвращает эти строки в массиве. Линии разделяются sep.

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

Я стал чувствительным к этому много лет назад, когда загружал очень большой файл данных в приложение Perl на HP mini mini, которым я управлял. Приложение приостанавливалось на пару секунд, и я не мог понять, почему. Я зашел в отладчик и не смог найти проблему. Наконец, отслеживая запуск с использованием приложений печати старой школы, я изолировал паузы в файле "slurp". У меня было много оперативной памяти и много вычислительной мощности, но Perl не выделял достаточно памяти. Я перешел на чтение по строчке, и приложение пролетел через его обработку. Ruby, как и Perl, имеет хороший ввод-вывод и очень быстро читает большой файл, когда он читает строки за строкой. Я никогда не нашел достаточной причины для размывания текстового файла, за исключением случаев, когда он может иметь контент, который я хочу разбросать по нескольким строкам, но это не обычное явление.

Ответ 2

Возможно, я полностью не понимаю проблему, но вы можете сделать что-то вроде:

File.readlines("path/to/file.txt").select { |line| line =~ /ohn/ }

чтобы получить массив всех строк, соответствующих вашим критериям.

Ответ 3

query = 'ohn'
names = File.readlines('names.txt')
matches = names.select { |name| name[/#{query}/i] }
#=> ["John Smith"]

Удалите i в конце регулярного выражения, если вы хотите, чтобы запрос был чувствительным к регистру.

Ответ 4

Старый вопрос, но Array#grep также можно использовать для поиска списка строк

File.readlines("names.txt").grep /#{query}/i