Одно регулярное выражение, чтобы управлять ими всеми (эффективно)? - PullRequest
2 голосов
/ 02 сентября 2010

Эй, ребята, я пытался проанализировать HTML-файлы, чтобы очистить их от текста, и время от времени я получаю некоторые действительно странные символы, такие как à€œ.Я решил, что именно «умные кавычки» или фигурные знаки препинания вызывают все мои проблемы, поэтому мое временное исправление заключалось в поиске и замене всех этих символов соответствующими кодами HTML по отдельности.Мой вопрос заключается в том, существует ли такой способ использования одного регулярного выражения (или чего-то еще) для поиска по строке только один раз и замены того, что ему нужно, исходя из того, что там есть?Мое решение сейчас выглядит следующим образом:

line = line.replaceAll( "“", "“" ).replaceAll( "”", "”" );
line = line.replaceAll( "–", "–" ).replaceAll( "—", "—" );
line = line.replaceAll( "‘", "‘" ).replaceAll( "’", "’" ); 

По той или иной причине просто кажется, что может быть лучший и, возможно, более эффективный способ сделать это.Любой вклад приветствуется.

Спасибо,
-Бретт

Ответы [ 4 ]

3 голосов
/ 02 сентября 2010

Как заявлено другими; Рекомендуемый способ позаботиться об этих символах - настроить параметры кодировки.

Для сравнения, вот метод перекодирования последовательностей UTF-8 в виде сущностей HTML с использованием регулярного выражения:

import java.util.regex.*;

public class UTF8Fixer {
    static String fixUTF8Characters(String str) {
        // Pattern to match most UTF-8 sequences:
        Pattern utf8Pattern = Pattern.compile("[\\xC0-\\xDF][\\x80-\\xBF]{1}|[\\xE0-\\xEF][\\x80-\\xBF]{2}|[\\xF0-\\xF7][\\x80-\\xBF]{3}");

        Matcher utf8Matcher = utf8Pattern.matcher(str);
        StringBuffer buf = new StringBuffer();

        // Search for matches
        while (utf8Matcher.find()) {
            // Decode the character
            String encoded = utf8Matcher.group();
            int codePoint = encoded.codePointAt(0);
            if (codePoint >= 0xF0) {
                codePoint &= 0x07;
            }
            else if (codePoint >= 0xE0) {
                codePoint &= 0x0F;
            }
            else {
                codePoint &= 0x1F;
            }
            for (int i = 1; i < encoded.length(); i++) {
                codePoint = (codePoint << 6) | (encoded.codePointAt(i) & 0x3F);
            }
            // Recode it as an HTML entity
            encoded = String.format("&#%d;", codePoint);
            // Add it to the buffer
            utf8Matcher.appendReplacement(buf,encoded);
        }
        utf8Matcher.appendTail(buf);
        return buf.toString();
    }

    public static void main(String[] args) {
        String subject = "String with \u00E2\u0080\u0092strange\u00E2\u0080\u0093 characters";
        String result = UTF8Fixer.fixUTF8Characters(subject);
        System.out.printf("Subject: %s%n", subject);
        System.out.printf("Result: %s%n", result);
    }
}

Выход:

Subject: String with “strange” characters
Result: String with &#8210;strange&#8211; characters

2 голосов
/ 02 сентября 2010

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

Ищите внешние библиотеки для выполнения этой задачи.Примером может быть: JSoup .На их веб-странице также есть учебник, который вы можете использовать.

2 голосов
/ 02 сентября 2010

Ваш файл выглядит в кодировке UTF-8, но вы читаете его, как если бы он был в однобайтовой кодировке, такой как windows-1252. UTF-8 использует три байта для кодирования каждого из этих символов, но когда вы декодируете его как windows-1252, каждый байт обрабатывается как отдельный символ.

При работе с текстом всегда следует указывать кодировку, если это возможно; не позволяйте системе использовать кодировку по умолчанию. В Java это означает использование InputStreamReader и OutputStreamWriter вместо FileReader и FileWriter. Любой достаточно хороший текстовый редактор должен также указывать кодировку.

Что касается вашего фактического вопроса, нет, в Java нет встроенного средства для динамических замен (в отличие от большинства других разновидностей регулярных выражений). Но не так уж сложно написать свой или, еще лучше, использовать тот, который написал кто-то другой. Я отправил сообщение от Эллиотта Хьюза в этот ответ .

И еще одна вещь: в вашем примере кода вы используете replaceAll() для замены, что является чрезмерным убийством и возможным источником ошибок. Поскольку вы сопоставляете буквенный текст, а не регулярные выражения, вместо этого следует использовать replace(CharSequence,CharSequence). Таким образом, вам никогда не придется беспокоиться о случайном включении метасимвола регулярных выражений и переходе в тупик.

0 голосов
/ 02 сентября 2010

Не используйте регулярные выражения для HTML. Используйте настоящий парсер.

Это также поможет вам обойти любые кодировки символов, с которыми вы можете столкнуться.

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