11

I try to get URLs in text. So, before, I used such an expression:

let re = NSRegularExpression(pattern: "https?:\\/.*", options: nil, error: nil)!

But I had a problem when a user input URLs with Capitalized symbols (like Http://Google.com, it doesn't match it).

I tried:

let re = NSRegularExpression(pattern: "(h|H)(t|T)(t|T)(p|P)s?:\\/.*", options: nil, error: nil)!

But nothing happened.

Sahil Kapoor
  • 11,183
  • 13
  • 64
  • 87
nabiullinas
  • 1,185
  • 4
  • 20
  • 41

5 Answers5

8

You turn off case sensitivity using an i inline flag in regex, see Foundation Framework Reference for more information on available regex features.

(?ismwx-ismwx)
Flag settings. Change the flag settings. Changes apply to the portion of the pattern following the setting. For example, (?i) changes to a case insensitive match.The flags are defined in Flag Options.

For readers:

Matching an URL inside larger texts is already a solved problem, but for this case, a simple regex like

(?i)https?://(?:www\\.)?\\S+(?:/|\\b)

will do as OP requires to match only the URLs that start with http or https or HTTPs, etc.

Community
  • 1
  • 1
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Does not work - Input - Test web http://google.com/hp new test okay bye Output - http://google.com/hp new test okay bye – Deb Aug 21 '15 at 22:55
  • What do you mean? Could you post *visible* proof that it does not work? The point here is that `Http://Google.com` and `http://google.com` should be matched with `http://`. `(?i)` does turn case sensitivity off from the pattern. – Wiktor Stribiżew Aug 21 '15 at 23:03
  • Correct, OP needs to match only URLs containing `http` or `https`. This is the only requirement. My solution works for OP under current requirements. Please do not think them up. – Wiktor Stribiżew Aug 21 '15 at 23:08
  • Sorry about the downvote buddy. I can remove the downvote but SO wont let me do it unless you edit the answer again. The title of this question is a bit misleading. May be you could edit your answer to specify that? BTW I am in no way looking to make more points. Take it easy, buddy :-) Thanks – Deb Aug 21 '15 at 23:22
  • @Deb: I added a regex to match URLs that start with `http` or `https`. OP does not need to match others. – Wiktor Stribiżew Aug 21 '15 at 23:25
7

Swift 4

1. Create String extension

import Foundation

extension String {

    var isValidURL: Bool {
        guard !contains("..") else { return false }
    
        let head     = "((http|https)://)?([(w|W)]{3}+\\.)?"
        let tail     = "\\.+[A-Za-z]{2,3}+(\\.)?+(/(.)*)?"
        let urlRegEx = head+"+(.)+"+tail
    
        let urlTest = NSPredicate(format:"SELF MATCHES %@", urlRegEx)

        return urlTest.evaluate(with: trimmingCharacters(in: .whitespaces))
    }

}

2. Usage

"www.google.com".isValidURL
alegelos
  • 2,308
  • 17
  • 26
1

Try this - http?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?

    let pattern = "http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)?"
    var matches = [String]()
    do {
        let regex = try NSRegularExpression(pattern: pattern, options: NSRegularExpressionOptions(rawValue: 0))
        let nsstr = text as NSString
        let all = NSRange(location: 0, length: nsstr.length)
        regex.enumerateMatchesInString(text, options: NSMatchingOptions.init(rawValue: 0), range: all, usingBlock: { (result, flags, _) in
            matches.append(nsstr.substringWithRange(result!.range))
        })
    } catch {
        return [String]()
    }
    return matches
Nykholas
  • 503
  • 1
  • 6
  • 14
Deb
  • 1,918
  • 1
  • 18
  • 18
  • There is absolutely no need escaping a dot inside a character class. Why use so many capturing groups? You are not using any. – Wiktor Stribiżew Aug 21 '15 at 23:00
  • Thanks for you comment, but did you check the test case I posted against your comment? Thanks – Deb Aug 21 '15 at 23:03
  • Tried it and found deb's answer can match exactly the url. stribizhev's answer will match from http till end of the line, which is not a legal url. – Ripley Dec 20 '15 at 09:46
1

Make an exension of string

extension String {
var isAlphanumeric: Bool {
    return rangeOfString( "^[wW]{3}+.[a-zA-Z]{3,}+.[a-z]{2,}", options: .RegularExpressionSearch) != nil
}
}

call using like this

"www.testsite.edu".isAlphanumeric  // true
"flsd.testsite.com".isAlphanumeric //false
bikram sapkota
  • 1,106
  • 1
  • 13
  • 18
0

My complex solution for Swift 5.x

ViewController:

private func loadUrl(_ urlString: String) {
    guard let url = URL(string: urlString) else { return }
    let request = URLRequest(url: url)
    webView.load(request)
}

UISearchBarDelegate:

func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
    guard let text = searchBar.text else { return }
    
    if !text.isUrl() {
        let finalUrl = String(format: "%@%@", "https://www.google.com/search?q=", text)
        loadUrl(finalUrl)
        return
    }
    
    if text.starts(with: "https://") || text.starts(with: "http://") {
        loadUrl(text)
        return
    }

    let finalUrl = String(format: "%@%@", "https://", text)
    loadUrl(finalUrl)
}

String extension:

extension String {

    func isUrl() -> Bool {
        guard !contains("..") else { return false }
        
        let regex = "((http|https)://)?([(w|W)]{3}+\\.)?+(.)+\\.+[A-Za-z]{2,3}+(\\.)?+(/(.)*)?"
        let urlTest = NSPredicate(format:"SELF MATCHES %@", regex)
        
        return urlTest.evaluate(with: trimmingCharacters(in: .whitespaces))
    }

}
Arthur Stepanov
  • 511
  • 7
  • 4