2017-07-20 3 views
0

Envisager un printf-comme argument format. Quelque chose comme:regex - spécificateurs de type de capture dans la chaîne de format

printf("Hello %s, your rating is %i%%", name, percentage); 

Je veux utiliser regex pour capturer tous les spécificateurs (dans le cas ci-dessus, et %s%iet non%%).

J'ai commencé avec un modèle naïf (%[^%]), mais il capture à tort des choses comme %%f au lieu de "l'échapper". Bien sûr, %%%f doit être interprété comme un échappement "%", puis un spécificateur. J'ai pensé que j'avais besoin d'un motif plus complexe (peut-être lookbehind?), Mais je n'arrivais pas à le résoudre. Aucune suggestion? Note latérale: Je sais que mon modèle ne gère pas les spécificateurs de longueur et autres indicateurs de formatage tels que %2f etc., mais cela me convient car mon objectif est principalement d'énumérer et de compter les spécificateurs de format.

+0

Peut-être que vous avez besoin de spécifier plus quelles sont vos intentions. Pourquoi fais-tu ça? Avez-vous besoin d'utiliser regex, ou pouvez-vous faire une analyse de chaîne (par exemple, trouver et supprimer les caractères échappés)? – Derek

+0

En fin de compte, le but est d'écrire une série de fonctions d'encapsulation autour de 'printf',' sprintf', 'NSLog' etc. qui remplace les spécificateurs erronés, gère la mise en forme de l'objet objc et plus encore. Je peux itérer le tableau char à la main et marquer la chaîne de format, mais regex rendrait le code beaucoup plus propre. – Elist

+0

Je pense que l'itération à la main pourrait finir par être l'option la plus propre et la meilleure. Je ne suis pas un assistant de regex, mais je vais bien. Si cela doit être écrit par un assistant regex, cela peut rendre les choses plus compliquées que vous le souhaitez. – Derek

Répondre

1

D'une part, vous ne pouvez pas ignorer les caractères sans attraper accidentellement des choses comme %%f, donc vous devez utiliser soit match ou mettre un ^ (caret) au début de votre regex. D'autre part, dans ce cas, vous ne pouvez pas utiliser findall. Comme il n'y a pas de fonction matchall, le plus simple sera d'écrire votre propre boucle:

REG = re.compile('([^%]|%%)*(%[^%])') # a bunch of (non-% or %%), and then (% followed by non-%). 
def find_type_specifiers(st): 
    retval = [] 
    pos = 0 # where to start searching for next time 
    while True: 
     match = REG.match(st, pos) 
     if match is None: 
      return retval 
     retval.append(match.group(2)) 
     pos = match.end() 

Bien sûr, vous pouvez changer ce que vous ajoutez à retval si par exemple vous êtes également intéressé par les emplacements des prescripteurs. Ou passez à un compteur si vous voulez seulement le montant.