Многострочный поиск по регулярному выражению во всем файле - PullRequest
8 голосов
/ 02 октября 2009

Я нашел множество примеров для замены текста в файлах с помощью регулярных выражений. Однако все сводится к двум версиям:
1. Переберите все строки в файле и примените регулярное выражение к каждой отдельной строке
2. Загрузите весь файл.

Нет. 2 Невозможно использовать «мои» файлы - они около 2 ГБ ...
Что касается № 1: В настоящее время это мой подход, однако мне было интересно ... Что если нужно применить регулярное выражение, охватывающее более одной строки?

Ответы [ 6 ]

2 голосов
/ 19 ноября 2009

Вот ответ:
Легкого пути нет

Я нашел StreamRegex-Class , который мог бы делать то, что я ищу.
Из того, что я мог понять алгоритм:

  • Начало в начале файла с пустым буфером
  • до (
    • добавить часть файла в буфер
    • если в буфере есть совпадение
      • отметить матч
      • удалить из буфера все данные, появившиеся до конца матча
  • ) пока что-то осталось от файла

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

1 голос
/ 02 октября 2009

Regex - это не тот путь, особенно с таким большим количеством текста. Создайте свой собственный маленький парсер:

  • читать файл построчно;
  • для каждой строки:
    • цикл по строковому символу по символу, отслеживая любой открывающая / закрывающая строковые литералы
    • когда вы встречаете «/ *» (а вы не «внутри» строки), сохранить этот номер смещения и цикл, пока не встретите сначала '* /' и сохраните это число

Это даст вам все начальные и конечные числа смещений блоков комментариев. Теперь вы сможете заменить их, создав временный файл и записав текст из исходного файла во временный файл (и записав что-нибудь еще, если вы, конечно, находитесь внутри блока комментария).

Редактировать: исходные файлы 2 ГБ ??

0 голосов
/ 19 ноября 2009

Если вы не возражаете немного запачкать руки (и ваше регулярное выражение достаточно простое, или, возможно, у вас есть сильное стремление к скорости и вы не возражаете немного страдать), вы можете использовать Ragel . Он может быть ориентирован на C #, хотя сайт не упоминает об этом. Вам нужно будет обернуть FileStream для предоставления буферизованного индексатора или использовать файл с отображением памяти (с небезопасными указателями) в 64-битном процессе, чтобы использовать его с большими файлами.

0 голосов
/ 03 октября 2009

Я с Бартом; Вы действительно должны использовать какой-то парсер для этого.

Или, если вы не против порождать дочерний процесс, вы можете просто использовать sed (есть собственный порт в windows или вы можете использовать Cygwin )

0 голосов
/ 02 октября 2009

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

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

0 голосов
/ 02 октября 2009

Возможно, вы могли бы загружать по 2 строки за раз (или больше, в зависимости от того, сколько строк, по вашему мнению, будут совпадать ваши совпадения), и перекрывать их, например: строки загрузки 1-2, затем строки загрузки следующего цикла 2-3, следующая загрузка 3-4; и сделайте ваши многострочные регулярные выражения по обеим объединенным строкам в каждом цикле.

...