В этом посте показано, как вешать отступ для длинного абзаца с помощью регулярного выражения. Метод учитывает границы слов, что означает, что он не будет разбивать слова для отступа. Чтобы проиллюстрировать проблему, рассмотрим следующий пример:
В последние годы предпринимаются все более активные усилия по извлечению отношений между сущностями из текста на естественном языке. В этой диссертации я остановлюсь на различных аспектах распознавания биомедицинских отношений между субъектами, о которых сообщается в научных статьях.
Выход должен быть:
|
1
2
3
4
|
There has been an increasing effort in recent years to extract relations between entities from natural language text. In this dissertation, I will focus on various aspects of recognizing biomedical relations between entities reported in scientific articles. |
Мой метод
Нам нужно регулярное выражение, чтобы разбить абзац на последовательность строк фиксированной длины. Предположим, что ширина текста равна 80, а отступ равен 3, длина первой строки равна 80. Длина всех остатков равна 77.
Основной процесс алгоритма заключается в следующем
- Получите первые 80 символов
- Для остальных строк замените точки разделения тремя пробелами.
Чтобы найти точки расщепления, мы используем регулярное выражение (.{1,77})\s+ . Это регулярное выражение ищет подстроку, длина которой меньше и равна 77, а последний символ не является пробелом. Найдя его, заменим группу ( $1 ) на $1\n . Поэтому код Java должен выглядеть следующим образом
|
1
2
3
|
String regex = "(.{1,77})\\s+";String replacement = " $1\n";text.replaceAll(regex, replacement); |
Это регулярное выражение прекрасно работает, за исключением последней строки. Если данный текст не заканчивается пробелом, как \n , последняя строка не будет обработана правильно. Рассмотрим последнюю строку как
|
1
|
in scientific articles. |
В последнем поиске регулярное выражение не может найти пробелы в конце строки, поэтому оно будет находить пространство между «научными» и «статьями». В результате мы получим
|
1
2
3
|
... in scientificarticles. |
Чтобы преодолеть эту проблему, я добавляю фальшивую «\ n» в конце абзаца. После форматирования удаляю потом.
Другая часть кода тривиальна. Здесь я прилагаю свой исходный код. Я использую общие библиотеки Apache для генерации отступов и подтверждения правильности отступа. Для более свежих кодов, вы можете проверить мой Github
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
/** * Format a paragraph to that has all lines but the first indented. * * @param text text to be formatted * @param hangIndent hanging indentation. hangIndent >= 0 * @param width the width of formatted paragraph * @param considerSpace true if only split at white spaces. * @return */ public static String hangIndent(String text, int hangIndent, int width, boolean considerSpace) { Validate.isTrue( hangIndent >= 0, "hangIndent should not be negative: %d", hangIndent); Validate.isTrue(width >= 0, "text width should not be negative: %d", width); Validate.isTrue( hangIndent < width, "hangIndent should not be less than width: " + "hangIndent=%d, width=%d", hangIndent, width); StringBuilder sb = new StringBuilder(text.substring(0, hangIndent)); // Needed to handle last line correctly. // Will be trimmed at last text = text.substring(hangIndent) + "\n"; // hang indent String spaces = org.apache.commons.lang3.StringUtils .repeat(' ', hangIndent); String replacement = spaces + "$1\n"; String regex = "(.{1," + (width - hangIndent) + "})"; if (considerSpace) { regex += "\\s+"; } text = text.replaceAll(regex, replacement); // remove first spaces and last "\n" text = text.substring(hangIndent, text.length() - 1); return sb.append(text).toString(); } |
Связанных с работой
Есть много других способов реализовать функцию висячего отступа. Самым простым кажется сначала разбить абзац на слова, а затем использовать счетчик для вычисления длины текущей строки. Всякий раз, когда он превышает максимальную длину, мы добавляем новую строку и отступ.
Я не уверен, какой способ более эффективен, но абсолютно нерегулярный способ легче реализовать и поддерживать. Поэтому я думаю, что основной смысл этого поста — узнать что-то « НОВОЕ ».