2016-04-26 23 views
0

文字列「ab ad adk fda kla kad ab ab kd」があります。私はabのすべての範囲を取得したい(ここでabは3つの位置に存在するので、3つの範囲を取得する必要がある)。通常のシナリオでは、コードはうまくいきますが、検索テキストが「。」の場合、間違った結果になります文字列内の部分文字列のすべての範囲を即座に取得します

do { 
    let regEx = try NSRegularExpression(pattern: searchText, options: NSRegularExpressionOptions.CaseInsensitive) 

    let matchesRanges = regEx.matchesInString(attributedText.string, options:[], range: NSMakeRange(0, attributedText.string.length)) 

    for rng in matchesRanges { 
     let wordRange = rng.rangeAtIndex(0) 
    } 
} catch { 
    ... 
} 
+0

とそれが間違っていることを説明してください – Wain

+0

あなたが望む結果を詳細に説明してください? – PSS

+0

'.'は「任意の文字」を意味する特殊文字です – redent84

答えて

0

あなたは以下のコードによって特定の文字列を数えるのoccurance得ることができます:

let str: NSMutableString = "ab ad adk fda kla kad ab ab kd" 
let count = str.replaceOccurrencesOfString("ab", withString: "ab", options: NSStringCompareOptions.LiteralSearch, range: NSMakeRange(0, str.length)) 
+0

いいえ範囲を取得したいので、その範囲に属性を適用できます。 –

2

は、私は、このような解決策を示唆している:脇

import Foundation 

extension String { 

    func rangesOfString(s: String) -> [Range<Index>] { 
     let re = try! NSRegularExpression(pattern: NSRegularExpression.escapedPatternForString(s), options: []) 
     return re.matchesInString(self, options: [], range: nsRange(startIndex ..< endIndex)).flatMap { range($0.range) } 
    } 

    func range(nsRange : NSRange) -> Range<Index>? { 
     let utf16from = utf16.startIndex.advancedBy(nsRange.location, limit: utf16.endIndex) 
     let utf16to = utf16from.advancedBy(nsRange.length, limit: utf16.endIndex) 

     if let from = String.Index(utf16from, within: self), 
      let to = String.Index(utf16to, within: self) 
     { 
      return from ..< to 
     } else { 
      return nil 
     } 
    } 

    func nsRange(range : Range<Index>) -> NSRange { 
     let utf16from = String.UTF16View.Index(range.startIndex, within: utf16) 
     let utf16to = String.UTF16View.Index(range.endIndex, within: utf16) 
     return NSRange(location: utf16.startIndex.distanceTo(utf16from), length: utf16from.distanceTo(utf16to)) 
    } 

} 

print("[^x]? [^x]? [^x]?".rangesOfString("[^x]?")) // [Range(0..<5), Range(6..<11), Range(12..<17)] 

主な問題は、このコードはまた、道を示してい変換する NSRangeからRange<String.Index>this postに基づく)。

+0

他のすべての特殊文字を処理しますか? –

+0

私は[NSRegularExpression.escapedPatternForString()](https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSRegularExpression_Class/#//apple_ref/occ/clm/NSRegularExpression/escapedPatternForString :)を使用して可能なパターンメタキャラクタ。これは信頼できる解決策でなければなりません。 – werediver

+0

これらの範囲 NSRangeの変換はよくわかりますhttp://stackoverflow.com/a/30404532/1187415 :) –

1

正規表現を使用しているため、特別な意味を持つ文字に注意する必要があります。.はそのうちの1つです。

あなたはサブストリングの検索をやっている場合は、私が代わりに、古き良きrangeOf ...メソッドを使用することをお勧め:

func rangeOfString(_ searchString: String, 
      options mask: NSStringCompareOptions, 
      range searchRange: NSRange) -> NSRange 

ちょうどあなたの文字列にそのメソッドを呼び出しておく(とsearchRangeを調整)、それ以上一致するものが見つからなくなるまで続けます。

2

次のソリューションは、ネイティブスウィフト4機能range(of:, options:, range:, locale:)を使用しています):あなたが試したものを示す必要がある

extension String { 
    func ranges(of substring: String, options: CompareOptions = [], locale: Locale? = nil) -> [Range<Index>] { 
     var ranges: [Range<Index>] = [] 
     while let range = self.range(of: substring, options: options, range: (ranges.last?.upperBound ?? self.startIndex)..<self.endIndex, locale: locale) { 
      ranges.append(range) 
     } 
     return ranges 
    } 
} 

(スウィフト4は、その後Range<Index>からNSRangeに変換するために、ネイティブAPIを提供)

+0

正規表現を使用すると、状況によっては無限ループが発生する可能性があります。この回答を避ける方法を確認してください。https://stackoverflow.com/a/32306142/2303865 –

関連する問題