Comment scinder une chaîne dans une liste de mots en TCL, ignorant les espaces?

En gros, j'ai une chaîne qui se compose de plusieurs, séparés par des espaces, des mots. La chose est, cependant, il peut y avoir plusieurs espaces au lieu d'un seul qui sépare les mots. C'est pourquoi [split] ne pas faire ce que je veux:

split "a    b"

me donne ceci:

{a {} {} {} b}

au lieu de cela:

{a b}

Cherchant sur Google, j'ai trouvé une page sur le tcler's wiki, où un utilisateur a demandé plus ou moins la même question.

Une solution proposée devrait ressembler à ceci:

split [regsub -all {\s+} "a    b" " "]

qui semble fonctionner pour chaîne simple. Mais une chaîne de test tels que [string repeat " " 4] (utilisé chaîne de répéter parce que StackOverflow bandes de multiples espaces) entraînera regsub le retour " ", qui split serait divisée en {{} {}} au lieu d'une liste vide.

Une autre solution proposée était celle-ci, à force d'une réinterprétation de la chaîne comme une liste:

lreplace "a   list   with many   spaces" 0 -1

Mais si il y a une chose que j'ai appris à propos de TCL, c'est que vous ne devez jamais utiliser les fonctions de liste (en commençant par l) sur les cordes. Et en effet, celui-ci va s'étouffer sur des chaînes de caractères contenant des caractères spéciaux (à savoir { et }):

lreplace "test    \{a b\}"

retourne test {a b} au lieu de test \{a b\} (ce qui je veux, chaque mot séparé par un espace divisé en un seul élément de la liste).

Encore une autre solution a été d'utiliser un "filtre":

proc filter {cond list} {
    set res {}
    foreach element $list {if [$cond $element] {lappend res $element}}
    set res
}

Vous pouvez l'utiliser comme ceci:

filter llength [split "a   list   with many   spaces"]

De nouveau, même problème. Ce serait d'appel llength sur une chaîne de caractères, qui peuvent contenir de caractères spéciaux (encore une fois, { et }) - passer "\{b\}" TCL se plaindre d'un "inégalée ouvrir accolade dans la liste".

J'ai réussi à le faire fonctionner en modifiant le filter fonction, l'ajout d'un {*} en face de $cond dans le si, si je pouvais l'utiliser avec string length au lieu de llength, qui semblait fonctionner pour chaque entrée possible j'ai essayé de l'utiliser jusqu'à présent.

Est cette solution de sécurité à utiliser comme il est maintenant? Serait-il étouffer sur certaines spéciales d'entrée je n'ai pas testé jusqu'à présent? Ou, est-il possible de faire cette droit dans un moyen plus simple?

OriginalL'auteur Jerry | 2012-11-14