2011-01-19 6 views
5

웹 사이트에서이 정규 표현식을 발견했습니다. 거기서 최고의 URL 검증 표현이라고 말하면서 나는 동의한다. Diego Perini가 그것을 만들었습니다.URL 유효성을 검사하는 NSRegularExpression

내가 직면 한 문제는 objective-C과 함께 사용하여 문자열의 URL을 감지하려고 할 때의 문제입니다. 나는 NSRegularExpressionAnchorsMatchLines, NSRegularExpressionIgnoreMetacharacters 및 다른 사람과 같은 선택권을 시도했다, 그러나 아직도 운이 없다.

표현식이 Objective-C에 적합하지 않습니까? 내가 놓친 게 있니? 어떤 아이디어?

존 그루버 (John Gruber)의 정규식을 사용해 보았지만 잘못된 URL이 있으면 실패합니다.

 Regular Expression         Explanation of expression      

^             match at the beginning 
//Protocol identifier 
(?: 
    (?:https?|ftp         http, https or ftp 
    ):\\/\\/          :// 
)?             optional 
// User:Pass authentication 
(?: 
    ^\\s+           non white spaces, 1 or more times 
    (?: 
     :^\\s*          : non white spaces, 0 or more times, optionally 
    )[email protected]            @ 
)?             optional 
//Private IP Addresses        ?! Means DO NOT MATCH ahead. So do not match any of the following 
(?: 
    (?!10           10               10.0.0.0 - 10.999.999.999 
     (?: 
      \\.\\d{1,3}        . 1 to 3 digits, three times 
     ){3} 
    ) 
    (?!127           127               127.0.0.0 - 127.999.999.999 
     (?: 
      \\.\\d{1,3}        . 1 to 3 digits, three times 
     ){3} 
    ) 
    (?!169\\.254         169.254              169.254.0.0 - 169.254.999.999 
     (?: 
      \\.\\d{1,3}        . 1 to 3 digits, two times 
     ){2} 
    ) 
    (?!192\\.168         192.168              192.168.0.0 - 192.168.999.999 
     (?: 
      \\.\\d{1,3}        . 1 to 3 digits, two times 
     ){2} 
    ) 
    (?!172\\.          172.              172.16.0.0 - 172.31.999.999 
     (?:                            
      1[6-9]         1 followed by any number between 6 and 9 
      |          or 
      2\\d         2 and any digit 
      |          or 
      3[0-1]         3 followed by a 0 or 1 
     ) 
     (?: 
      \\.\\d{1,3}        . 1 to 3 digits, two times 
     ){2} 
    ) 
    //First Octet IPv4        // match these. Any non network or broadcast IPv4 address 
    (?: 
     [1-9]\\d?         any number from 1 to 9 followed by an optional digit  1 - 99 
     |           or 
     1\\d\\d          1 followed by any two digits        100 - 199 
     |           or 
     2[01]\\d         2 followed by any 0 or 1, followed by a digit    200 - 219 
     |           or 
     22[0-3]          22 followed by any number between 0 and 3     220 - 223 
    ) 
    //Second and Third Octet IPv4 
    (?: 
     \\.           . 
     (?: 
      1?\\d{1,2}        optional 1 followed by any 1 or two digits     0 - 199 
      |          or 
      2[0-4]\\d        2 followed by any number between 0 and 4, and any digit  200 - 249 
      |          or 
      25[0-5]         25 followed by any numbers between 0 and 5     250 - 255 
     ) 
    ){2}           two times 
    //Fourth Octet IPv4 
    (?: 
     \\.           . 
     (?: 
      [1-9]\\d?        any number between 1 and 9 followed by an optional digit 1 - 99 
      |          or 
      1\\d\\d         1 followed by any two digits        100 - 199 
      |          or 
      2[0-4]\\d        2 followed by any number between 0 and 4, and any digit  200 - 249 
      |          or 
      25[0-4]         25 followed by any number between 0 and 4     250 - 254 
     ) 
    ) 
    //Host name 
    |            or     
    (?: 
     (?: 
      [a-z\u00a1-\uffff0-9]+-?    any letter, digit or character one or more times with optional - 
     )*           zero or more times 
     [a-z\u00a1-\uffff0-9]+      any letter, digit or character one or more times 
    ) 
    //Domain name 
    (?: 
     \\.           . 
     (?: 
      [a-z\u00a1-\uffff0-9]+-?    any letter, digit or character one or more times with optional - 
     )*           zero or more times 
     [a-z\u00a1-\uffff0-9]+      any letter, digit or character one or more times 
    )*            zero or more times 
    //TLD identifier 
    (?: 
     \\.           . 
     (?: 
      [a-z\u00a1-\uffff]{2,}     any letter, digit or character more than two times 
     ) 
    ) 
) 
//Port number 
(?: 
    :\\d{2,5}          : followed by any digit, two to five times, optionally 
)?    
//Resource path 
(?: 
    \\/[^\\s]*         /followed by an optional non space character, zero or more times 
)?             optional 
$             match at the end 

편집 나는 내가 다음 코드 표현을 사용하고 말을 잊었다 생각 : (부분 코드)

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)]; 

답변

9
^(?i)(?:(?:https?|ftp):\\/\\/)?(?:\\S+(?::\\S*)[email protected])?(?:(?:[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]; 

결과를 : URL과 이메일을 클릭 일부 포함 된 HTML,와 UIWebView. 또한

NSError *error = NULL; 
NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:@"(?i)(?:(?:https?):\\/\\/)?(?:\\S+(?::\\S*)[email protected])?(?:(?:[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"); 
} 

은 가끔하면 응용 프로그램이 응답을하게됩니다 미래

정규 표현식에 누군가가 도움이되기를 바랍니다 시도 할 수 dataDetectorTypes = UIDataDetectorTypeNone

을 설정하는 것을 잊지, 그래서 나는 그루버의 정기를 사용하기로 결정하지 마십시오 프로토콜 또는 www가없는 URL을 인식하도록 수정 된 표현식 : part :

+0

좋은 게시물에 대한 고마워. – Jhaliya

+0

업데이트 된 Gruber 코드는 좋지만 "google.com"과 일치하지 않지만 "google.comm"및 "google.co.uk"와 일치합니다. – mootymoots

+0

많은 정규식에 감사드립니다. 정말 훌륭합니다. –

7

내가 뭔가를 놓치고 있습니까?

당신을 위해이 작업을 수행 할 수있는 기본 기능이 없습니다. NSDataDetector이라는 편리한 객체가 있습니다. 특정 데이터 "유형"(예 : NSTextCheckingTypeLink)을 찾은 다음 -matchesInString:options:range:을 요청하십시오.

Here's an earlier answer of mine showing how to use it.

+0

빠른 대답을 부탁드립니다. 나는 전에 그것을 시험해 보았지만 .asia, .info와 같은 몇몇 URL을 인식하지 못한다. URL이 http://healthyhomes.asia처럼 잘 형성되지 않았을 때이다. 그래서 나는 정규적인 URL을 사용하고있다. 표현. 온라인 테스터를 사용하여 프로토콜 부분과 함께 healthhomes.asia 또는 info.info를 탐지합니다. – GianPac

+0

www.google.c의 경우 @Dave DeLong이 실패했습니다. – JAHelia

+0

2017 업데이트 : 방금 NSDataDetector를 확인했습니다. 'info.info'는 이제는 작동하지만'healthyhomes.asia'는 여전히 않습니다. 'www.google.c'은 효과가 있습니다. 'Foundation'의'NSDataDetector'가 그러한 URL을 지원하지 않는다면 Safari (iOS 및 데스크탑)가'healthyhomes.asia'를 방문 할 수있는 방법에 대해서는 알지 못합니다. –

관련 문제