2016-09-26 1 views
1

J'essaye d'analyser un fichier Localizable.string pour un petit projet dans swift sur MacOS. Je veux juste récupérer toutes les clés et les valeurs dans un fichier pour les trier dans un dictionnaire. Pour ce faire j'ai utilisé regex avec la classe de cacao NSRegularExpression.en essayant d'analyser un fichier Localizable.string pour un petit projet dans swift sur MacOS

Voici à quoi ressemblent ces fichiers comme:

"key 1" = "Value 1"; 
"key 2" = "Value 2"; 
"key 3" = "Value 3"; 

Voici mon code qui est censé obtenir les clés et les valeurs du fichier chargé dans un String:

static func getDictionaryFormText(text: String) -> [String: String] { 
    var dict: [String : String] = [:] 
    let exp = "\"(.*)\"[ ]*=[ ]*\"(.*)\";" 

    for line in text.components(separatedBy: "\n") { 
     let match = self.matches(for: exp, in: line) 
     // Following line can be uncommented when working 
     //dict[match[0]] = match[1] 
     print("(\(match.count)) matches = \(match)") 
    } 
    return dict 
} 

static func matches(for regex: String, in text: String) -> [String] { 
    do { 
     let regex = try NSRegularExpression(pattern: regex) 
     let nsString = text as NSString 
     let results = regex.matches(in: text, range: NSRange(location: 0, length: nsString.length)) 
     return results.map { nsString.substring(with: $0.range) } 
    } catch let error as NSError { 
     print("invalid regex: \(error.localizedDescription)") 
     return [] 
    } 
} 

Lors de l'exécution de cette code avec l'exemple Localisable fourni ici est la sortie:

(1) matches = ["\"key 1\" = \"Value 1\";"] 
(1) matches = ["\"key 2\" = \"Value 2\";"] 
(1) matches = ["\"key 3\" = \"Value 3\";"] 

Il semble que le match ne s'arrête pas après la première occurrence ". Lorsque j'essaie la même expression \"(.*)\"[ ]*=[ ]*\"(.*)\"; sur regex101.com la sortie est correcte cependant. Qu'est-ce que je fais mal ?

+1

Votre sortie semble montrer le bon résultat. Peut-être que vous ne comprenez pas la spécification de 'NSRegularExpression' ou 'NSTextCheckingResult'. Quel résultat attendez-vous avec votre code pour ce texte d'entrée? – OOPer

+1

[* Certaines personnes, confrontées à un problème, pensent "je sais, j'utiliserai des expressions régulières". Maintenant, elles ont deux problèmes. * - Jamie Zawinski] (http://regex.info/blog/2006-09 -15/247) –

+0

Vous avez raison, j'ai effectivement résolu ce problème après avoir posté, j'accédais juste au premier résultat à cause d'un malentendu sur la façon dont 'NSTextCheckingResult' a été conçu. Je vais mettre à jour ma question. – Edgar

Répondre

2

Votre fonction (de Swift extract regex matches?) Correspond à la totalité du motif seulement. Si vous êtes intéressé par les groupes de capture particuliers alors vous devez y accéder avec rangeAt() comme par exemple dans Convert a JavaScript Regex to a Swift Regex (pas encore mis à jour pour Swift 3).

Cependant, il y a une solution beaucoup plus simple, car les fichiers .strings utilisent effectivement un format possible des listes de propriétés et peut être lu directement dans un dictionnaire. Exemple:

if let url = Bundle.main.url(forResource: "Localizable", withExtension: "strings"), 
    let stringsDict = NSDictionary(contentsOf: url) as? [String: String] { 
    print(stringsDict) 
} 

Sortie:

["key 1": "Value 1", "key 2": "Value 2", "key 3": "Value 3"] 
+0

Merci Martin, c'est corrigé. Je posterai mon code au cas où cela aiderait d'autres personnes. Je ne connaissais pas la solution NSDictionary, c'est génial! – Edgar