2015-06-10 4 views
13

Java java.util.regex.MatcherreplaceFirst(...)/replaceAll(...) API возвращает строки, которые (при использовании размера кучи по умолчанию) могут привести к тому, что OOME будет вводить значения до 20-50M символов. Эти 2 метода могут быть легко переписаны на write до Writer с вместо того, чтобы создавать укусы, эффективно устраняя одну точку отказа.Java: замена регулярных выражений в больших файлах

Matcher «s factory method, однако, принимает только CharSequence с, что также, вероятно, бросить OOME, если я использую String S/S/StringBufferStringBuilder с.

Как обернуть java.io.Reader реализовать интерфейс CharSequence (учитывая тот факт, что мои регэкспы могут содержать обратные ссылки)? Есть ли другое решение, которое может заменять регулярные выражения в файлах и не является OOME-подверженным большим входам?

Другими словами, как реализовать функциональность, аналогичную функции GNU sed, в Java (как известно, sed имеет дело с файлами размером до нескольких терабайт, с той же поддержкой расширенных регулярных выражений)?

+2

Нужно ли вам заменять только одну строку за раз или поддерживать замену «весь файл за один раз»? –

+0

'Pattern.matcher()' не создает новую строку. Созданный объект 'Matcher' просто удерживает ссылку на переданную CharSequence. – nhahtdh

+7

' sed' обрабатывает файлы поэтапно, что является причиной того, что для больших файлов не требуется много памяти (если только файл имеет * очень * длинные строки или код дает указание запомнить много вещей). Если вы сделаете то же самое в Java (например, прочитайте строку, поработайте над ней, распечатайте ее, прочитайте следующую строку, промойте, повторите), вам потребуются одинаковые объемы памяти. Кстати, вас может заинтересовать [Unix4j] (https://code.google.com/p/unix4j/). – Wintermute

ответ

1

Так что вам нужно на самом деле sed поведение, которое вы можете выполнить его, делая что-то вроде этого:

String[] cmdArray = {"bash", "-c", "sed 's/YourRegex/YourReplaceStr/' inputfile > output"}; 
Process runCmd = Runtime.getRuntime().exec(cmdArray); 

Я положил пример оргии, но если вы хотите, чтобы запустить его на окнах можно установить sed команду через Cygwin и выполнить то же самое или просто установить SED команды для окон, которые вы можете скачать здесь:

http://gnuwin32.sourceforge.net/packages/sed.htm

для окон можно использовать:

String[] cmdArray = {"call", "sed 's/YourRegex/YourReplaceStr/' inputfile > output"}; 
Process runCmd = Runtime.getRuntime().exec(cmdArray); 

У меня нет окна, чтобы не испытать выше команды, вы, возможно, придется удалить call или изменить call к только sed. Другой вариант, вы можете попробовать это:

String[] cmdArray = {"cmd", "/c", "sed 's/YourRegex/YourReplaceStr/' inputfile > output"}; 
Process runCmd = Runtime.getRuntime().exec(cmdArray); 

В этом link вы можете найти dir пример выполнен из Java вы можете адаптировать его для использования СЭД.

+0

Спасибо, это отличное решение, но мне нужен мой код, чтобы он мог также работать на машинах Windows без любого Cygwin. – Bass

+0

@Bass вы можете использовать 'sed' в окнах тоже. Я обновил ответ со ссылкой, чтобы установить его –

Смежные вопросы