NSRegularExpression для проверки URL - PullRequest
5 голосов
/ 19 января 2011

Я нашел это регулярное выражение на веб-сайте.Говорят, что это лучшее выражение для проверки URL, и я согласен.Диего Перини создал его.

Проблема, с которой я сталкиваюсь, заключается в попытке использовать ее с objective-C для обнаружения URL-адресов в строках.Я пытался использовать такие параметры, как NSRegularExpressionAnchorsMatchLines, NSRegularExpressionIgnoreMetacharacters и другие, но все равно не повезло.

Не слишком ли хорошо отформатировано выражение для Objective-C?Я что-то пропустил?Есть идеи?

Я также попробовал регулярное выражение Джона Грубера, но он не работает с некоторыми недействительными URL.выражение в следующем коде: (частичный код)

NSError *error = NULL;
NSRegularExpression *detector = [NSRegularExpression regularExpressionWithPattern:[self theRegularExpression] options:0 error:&error];
NSArray *links = [detector matchesInString:theText options:0 range:NSMakeRange(0, theText.length)];

Ответы [ 2 ]

9 голосов
/ 20 января 2011
^(?i)(?:(?:https?|ftp):\\/\\/)?(?:\\S+(?::\\S*)?@)?(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:\\/[^\\s]*)?$

Лучшее регулярное выражение проверки URL, которое я нашел, и оно объяснено на мой вопрос.Он уже отформатирован для работы на Objective-C.Однако использование его с NSRegularExpression доставило мне много проблем, включая сбой моего приложения.RegexKitLite не было проблем с этим.Я не знаю, если это ограничение размера или какой-то флаг не установлен.Мой окончательный код выглядел так:

//First I take the string and put every word in an array, then I match every word with the regular expression
NSArray *splitIntoWordsArray = [textToMatch componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewLineCharacterSet]];
NSMutableString *htmlString = [NSMutableString stringWithString:textToMatch];
for (NSString *theText in splitIntoWordsArray){
    NSEnumerator *matchEnumerator = [theText matchEnumeratorWithRegex:theRegularExpressionString];
    for (NSString *temp in matchEnumerator){
        [htmlString replaceOccurrencesOfString:temp withString:[NSString stringWithFormat:@"<a href=\"%@\">%@</a>", temp, temp] options:NSLiteralSearch range:NSMakeRange(0, [htmlString length])];
    }
}
[htmlString replaceOccurrencesOfString:@"\n" withString:@"<br />" options:NSLiteralSearch range:NSMakeRange(0, htmlString.length)];
//embed the text on a webView as HTML
[webView loadHTMLString:[NSString stringWithFormat:embedHTML, [mainFont fontName], [mainFont pointSize], htmlString] baseURL:nil];

Результат: UIWebView с некоторым встроенным HTML, где URL и электронные письма кликабельны.Не забудьте установить dataDetectorTypes = UIDataDetectorTypeNone

Вы также можете попробовать

NSError *error = NULL;
NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:@"(?i)(?:(?:https?):\\/\\/)?(?:\\S+(?::\\S*)?@)?(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:\\/[^\\s]*)?" options:NSRegularExpressionCaseInsensitive error:&error];
if (error)
    NSLog(@"error");
NSString *someString = @"This is a sample of a sentence with a URL http://. http://.. http://../ http://? http://?? http://??/ http://# http://-error-.invalid/ http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com within it.";
NSRange range = [expression rangeOfFirstMatchInString:someString options:NSMatchingCompleted range:NSMakeRange(0, [someString length])];
if (!NSEqualRanges(range, NSMakeRange(NSNotFound, 0))){
    NSString *match = [someString substringWithRange:range];
    NSLog(@"%@", match);
}   
else {
    NSLog(@"no match");
}

Надеюсь, это поможет кому-нибудь в будущем

Регулярное выражение иногда приводит к зависанию приложенияпоэтому я решил использовать регулярное выражение Грубера, измененное для распознавания URL без протокола или части www:

(?i)\\b((?:[a-z][\\w-]+:(?:/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}/?)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))*(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:'\".,<>?«»“”‘’])*)
7 голосов
/ 19 января 2011

Я что-то упустил?

Вам не хватает встроенных вещей, чтобы сделать это для вас. Есть удобный объект с именем NSDataDetector. Вы создаете его для поиска определенных типов данных (например, NSTextCheckingTypeLink), а затем запрашиваете у него -matchesInString:options:range:.

Вот мой более ранний ответ, показывающий, как его использовать .

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