2012-03-06 20 views
12

Tôi đang sử dụng mã sau đây trên ứng dụng iPhone của mình, được lấy từ http://tinyurl.com/remarkablepixels để trích xuất tất cả các URL từ mã .html sọc.Sử dụng NSRegularExpression để trích xuất URL trên iPhone

Tôi chỉ có thể trích xuất URL đầu tiên, nhưng tôi cần một mảng chứa tất cả các URL. NSArray của tôi không trả về NSStrings cho mỗi URL, nhưng chỉ mô tả đối tượng.

Làm cách nào để làm cho số arrayOfAllMatches trả về tất cả các URL, dưới dạng NSStrings?

-(NSArray *)stripOutHttp:(NSString *)httpLine { 

// Setup an NSError object to catch any failures 
NSError *error = NULL; 

// create the NSRegularExpression object and initialize it with a pattern 
// the pattern will match any http or https url, with option case insensitive 

NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)?" options:NSRegularExpressionCaseInsensitive error:&error]; 

// create an NSRange object using our regex object for the first match in the string httpline 
NSRange rangeOfFirstMatch = [regex rangeOfFirstMatchInString:httpLine options:0 range:NSMakeRange(0, [httpLine length])]; 

NSArray *arrayOfAllMatches = [regex matchesInString:httpLine options:0 range:NSMakeRange(0, [httpLine length])]; 

// check that our NSRange object is not equal to range of NSNotFound 
if (!NSEqualRanges(rangeOfFirstMatch, NSMakeRange(NSNotFound, 0))) { 
    // Since we know that we found a match, get the substring from the parent string by using our NSRange object 

    NSString *substringForFirstMatch = [httpLine substringWithRange:rangeOfFirstMatch]; 

    NSLog(@"Extracted URL: %@",substringForFirstMatch); 
    NSLog(@"All Extracted URLs: %@",arrayOfAllMatches); 

    // return all matching url strings 
    return arrayOfAllMatches; 
} 

return NULL; 

}

Đây là sản lượng NSLog của tôi:

Extracted URL: http://mydomain.com/myplayer  
All Extracted URLs: (
    "<NSExtendedRegularExpressionCheckingResult: 0x106ddb0>{728, 53}{<NSRegularExpression: 0x106bc30> http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)? 0x1}", 
    "<NSExtendedRegularExpressionCheckingResult: 0x106ddf0>{956, 66}{<NSRegularExpression: 0x106bc30> http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)? 0x1}", 
    "<NSExtendedRegularExpressionCheckingResult: 0x106de30>{1046, 63}{<NSRegularExpression: 0x106bc30> http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)? 0x1}", 
    "<NSExtendedRegularExpressionCheckingResult: 0x106de70>{1129, 67}{<NSRegularExpression: 0x106bc30> http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)? 0x1}" 
) 

Trả lời

18

Phương pháp matchesInString:options:range: trả về một mảng các đối tượng NSTextCheckingResult. Bạn có thể sử dụng liệt kê nhanh để lặp qua mảng, kéo chuỗi con của mỗi kết hợp khỏi chuỗi ban đầu của bạn và thêm chuỗi con vào một mảng mới.

NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)?" options:NSRegularExpressionCaseInsensitive error:&error]; 

NSArray *arrayOfAllMatches = [regex matchesInString:httpLine options:0 range:NSMakeRange(0, [httpLine length])]; 

NSMutableArray *arrayOfURLs = [[NSMutableArray alloc] init]; 

for (NSTextCheckingResult *match in arrayOfAllMatches) {  
    NSString* substringForMatch = [httpLine substringWithRange:match.range]; 
    NSLog(@"Extracted URL: %@",substringForMatch); 

    [arrayOfURLs addObject:substringForMatch]; 
} 

// return non-mutable version of the array 
return [NSArray arrayWithArray:arrayOfURLs]; 
+0

đẹp! Làm việc như người ở! Cảm ơn rất nhiều jonkroll! – Winston

+4

Hoạt động awesomely! Có thể lấy tiêu đề từ sau> đến <. như nếu url là Google bạn có thể nhận được "Google"? – Maximilian

5

để có được tất cả các liên kết từ một chuỗi cho trước

NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:@"(?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`!()\\[\\]{};:'\".,<>?«»“”‘’]))" options:NSRegularExpressionCaseInsensitive error:NULL]; 
NSString *someString = @"www.facebook.com/link/index.php This is a sample www.google.com of a http://abc.com/efg.php?EFAei687e3EsA sentence with a URL within it."; 

NSArray *matches = [expression matchesInString:someString options:NSMatchingCompleted range:NSMakeRange(0, someString.length)]; 
for (NSTextCheckingResult *result in matches) { 
     NSString *url = [someString substringWithRange:result.range]; 
     NSLog(@"found url:%@", url); 
} 
+0

Không có lỗi giải pháp thanh lịch: NULL –

2

tôi thấy mình rất buồn nôn bởi sự phức tạp của hoạt động đơn giản này ("phù hợp với tất cả các chuỗi con") mà tôi tạo ra một thư viện nhỏ tôi gọi điện thoại khiêm tốn Unsuck làm tăng thêm sự tỉnh táo cho NSRegularExpression ở dạng các phương thức fromallMatches. Đây là cách bạn muốn sử dụng chúng:

NSRegularExpression *re = [NSRegularExpression from: @"(?i)\\b(https?://.*)\\b"]; // or whatever your favorite regex is; Hossam's seems pretty good 
NSArray *matches = [re allMatches:httpLine]; 

Hãy check out the unsuck source code on github và cho tôi biết tất cả những điều tôi đã làm sai :-)

Lưu ý rằng (?i) làm cho nó phân biệt dạng chữ do đó bạn không cần phải xác định NSRegularExpressionCaseInsensitive.

+0

Điều đó hoàn toàn tuyệt vời! Cảm ơn bạn đã chia sẻ thư viện của mình, Alex! – Winston

13

Hãy thử NSDataDetector

NSDataDetector *linkDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil]; 
NSArray *matches = [linkDetector matchesInString:text options:0 range:NSMakeRange(0, [text length])]; 
8

Với NSDataDetector sử dụng Swift:

let types: NSTextCheckingType = .Link 
var error : NSError? 

let detector = NSDataDetector(types: types.rawValue, error: &error)   
var matches = detector!.matchesInString(text, options: nil, range: NSMakeRange(0, count(text))) 

for match in matches { 
    println(match.URL!) 
} 

Using Swift 2.0:

let text = "http://www.google.com. http://www.bla.com" 
let types: NSTextCheckingType = .Link 

let detector = try? NSDataDetector(types: types.rawValue) 

guard let detect = detector else { 
    return 
} 

let matches = detect.matchesInString(text, options: .ReportCompletion, range: NSMakeRange(0, text.characters.count)) 

for match in matches { 
    print(match.URL!) 
} 

Using Swift 3.0

let text = "http://www.google.com. http://www.bla.com" 
let types: NSTextCheckingResult.CheckingType = .link 

let detector = try? NSDataDetector(types: types.rawValue) 

let matches = detector?.matches(in: text, options: .reportCompletion, range: NSMakeRange(0, text.characters.count)) 

for match in matches! { 
    print(match.url!) 
} 
+0

câu trả lời tuyệt vời. Ví dụ đơn giản với tất cả các phiên bản. +1 – mythicalcoder

+0

Tôi không nghĩ bạn cần. tùy chọn reportCompletion vì bạn không sử dụng enumerateMatches (trong: options: range: using :) – marchinram