#java #regex #email #email-headers
#java #регулярное выражение #Адрес электронной почты #email-заголовки
Вопрос:
Как можно извлечь строки с информацией о типе содержимого? В некоторых письмах эти заголовки могут состоять из 2, 3 или даже 4 строк, в зависимости от того, как оно было отправлено. Это один из примеров:
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 7bit
Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit
esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia
deserunt mollit anim id est laborum.
Я попробовал это регулярное выражение: ^(Content-.*:(.|n)*)*
но оно захватывает все.
Как я должен сформулировать свое регулярное выражение в Java, чтобы получить только часть:
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 7bit
Ответ №1:
Pattern regex = Pattern.compile("^Content-Type(?:.|\s)*?(?=n\s n)");
Это будет соответствовать всему, что начинается с Content-Type, до первой полностью пустой строки.
Комментарии:
1. Спасибо! Но почему я получаю a
StackOverFlowError
, когда использую его таким образом:mailContent.replaceFirst("^Content-Type(?:.|\s)*?(?=n\s n)", "");
2. @xEnOn Я, честно говоря, не знаю. Можете ли вы опубликовать образец на ideone.com ?
3. Я даже не знаю, какую часть кода я должен вставить в качестве образца. лол. Похоже, что все работает нормально, но пока я меняю регулярное выражение на предложенное вами, я получаю StackOverflowError . Итак, единственная проблема — это
replaceAll
строка. Это странно, потому что регулярное выражение, которое у вас было, работает, когда я помещаю его в тестер регулярных выражений. Но я не знаю, почему Java выдает эту ошибку.4. Я думаю, вам может потребоваться экранировать новые строки в шаблоне следующим образом:
"^Content-Type(?:.|\s)*?(?=\n\s \n)"
5. @ridgerunner Да, я тоже так думал, но мой инструмент настаивает на том, что n не следует экранировать дважды.
Ответ №2:
Вы можете попробовать это регулярное выражение
Pattern regex = Pattern.compile("Content-Type.*?(?=^\s*n?r?$)",
Pattern.DOTALL | Pattern.MULTILINE);
Комментарии:
1. Я пробовал это, но оно
find()
возвращает false. Он не находит часть.2. @xEnOn Я не уверен, почему он возвращает false, здесь он показывает совпадение regexr.com ? 2v20l
3. @xEnOn Я обновил регулярное выражение, можете ли вы попробовать его сейчас и сообщить мне, работает ли оно.
Ответ №3:
^Content-(.|n)*nn
Это будет соответствовать до пустой строки.
Ответ №4:
Проверьте соответствующие RFC для точного определения заголовков. IIRC по сути, вам нужно учитывать, что все, что содержит разрыв строки и один или несколько пробельных символов (например, пробел, неразрывный пробел, табуляция), является частью одной и той же строки заголовка. Я также считаю, что вам следует свернуть разрыв строки и пробелы в один элемент пробела (примечание: могут быть более сложные правила, поэтому проверьте RFC).
Только если новая строка напрямую начинается с непробельного символа, это следующий заголовок, и если за ним сразу следует другой разрыв строки, он завершает раздел заголовка и запускает раздел тела.
Кстати: почему бы просто не использовать JavaMail вместо того, чтобы изобретать велосипед?
Ответ №5:
Этот протестированный скрипт работает для меня:
import java.util.regex.*;
public class TEST
{
public static void main( String[] args )
{
String subjectString =
"Content-Type: text/plain;rn"
" charset="us-ascii"rn"
"Content-Transfer-Encoding: 7bitrn"
"rn"
"Lorem ipsum dolor sit amet, consectetur adipisicing elit,rn"
"sed do eiusmod tempor incididunt ut labore et dolore magnarn"
"aliqua. Ut enim ad minim veniam, quis nostrud exercitationrn"
"ullamco laboris nisi ut aliquip ex ea commodo consequat.rn"
"Duis aute irure dolor in reprehenderit in voluptate velitrn"
"esse cillum dolore eu fugiat nulla pariatur. Excepteur sintrn"
"occaecat cupidatat non proident, sunt in culpa qui officiarn"
"deserunt mollit anim id est laborum.rn";
String resultString = null;
Pattern regexPattern = Pattern.compile(
"^Content-Type.*?(?=\r?\n\s*\n)",
Pattern.DOTALL | Pattern.CASE_INSENSITIVE |
Pattern.UNICODE_CASE | Pattern.MULTILINE);
Matcher regexMatcher = regexPattern.matcher(subjectString);
if (regexMatcher.find()) {
resultString = regexMatcher.group();
}
System.out.println(resultString);
}
}
Оно работает для текста, имеющего как допустимые: rn
, так и (недопустимые, но обычно используемые в дикой природе): n
окончания строк в стиле Unix.