2017-09-29 11 views
0

ユーザーが指定した文字列から "@mentions"を解析しようとしています。正規表現自体はそれらを見つけるようですが、emojiが存在する場合、それが提供する範囲は正しくありません。Emojiが存在するときにNSRegularExpressionを使用すると不正な範囲が生成される

let text = " @joe " 
let tagExpr = try? NSRegularExpression(pattern: "@\\S+") 
tagExpr?.enumerateMatches(in: text, range: NSRange(location: 0, length: text.characters.count)) { tag, flags, pointer in 
    guard let tag = tag?.range else { return } 

    if let newRange = Range(tag, in: text) { 
     let replaced = text.replacingCharacters(in: newRange, with: "[email]") 
     print(replaced) 
    } 
} 

この tag =(所在地:7、長さ:2)を実行して

を、期待される結果は [email]

+1

あなたがNSRangeを必要とするときNSRegularExpressionsでNSStringのを使用してください - https://stackoverflow.com/a/39701370/3937 –

+0

'text.characters.count'は' NSRangeためtext.utf16.count'でなければなりません。 –

答えて

0

NSRegularExpression(および含むものである [email]oe

をプリントアウトNSRange)は、UTF16カウント/インデックスで動作します。その点については、NSString.countもUTF16カウントです。

しかし、あなたのコードでは、NSRegularExpressionにはtext.characters.countの長さを使用するように指示しています。これは、UTF16カウントではなく、合成文字の数です。あなたの文字列" @joe "には9文字の構成がありますが、12 UTF16のコード単位があります。実際にはNSRegularExpressionに最初の9個のUTF16コードユニットのみを見るように指示しています。つまり、末尾の"oe "を無視しています。

修正はlength: text.utf16.countに合格します。

let text = " @joe " 
let tagExpr = try? NSRegularExpression(pattern: "@\\S+") 
tagExpr?.enumerateMatches(in: text, range: NSRange(location: 0, length: text.utf16.count)) { tag, flags, pointer in 
    guard let tag = tag?.range else { return } 

    if let newRange = Range(tag, in: text) { 
     let replaced = text.replacingCharacters(in: newRange, with: "[email]") 
     print(replaced) 
    } 
} 
+1

これはhttps://stackoverflow.com/questions/46293204/swift-regex-doesnt-workで返答されたものなので、私はその*の複製としてクローズしました。なぜそれが "悪い詐欺"になって再開されたのか分かりません。 –

+0

@MartinR詐欺は変わったのですか?私はその複製をクリックして、それはhttps://stackoverflow.com/questions/39701316/use-regex-to-match-emojis-as-well-as-text-in-string/39701370#39701370でした。 'NSString'を推薦してください。 –

+0

ええと、私が提供したリンクは実際には投稿のコメントです。私は単に誤操作しましたか?アー。 –

関連する問題