2010-12-06 30 views

Répondre

15

Il y a une bibliothèque appelée cl-ppcre:

(cl-ppcre:regex-replace-all "qwer" "something to qwer" "replace") 
; "something to replace" 

installer via quicklisp.

+0

Il devrait être en commun LIS et je ne veux pas installer de bibliothèques supplémentaires. J'ai juste SLIME. –

+0

Le lisp commun n'inclut pas les expressions régulières perl-compatibe, car elles sont devenues une fonctionnalité standard des années plus tard. Vous pouvez trouver une implémentation simple de la chaîne de remplacement ici: http://cl-cookbook.sourceforge.net/strings.html#manip – koddo

+0

Note utile: si vous prévoyez de remplacer du texte par des barres obliques inverses, vous feriez mieux d'utiliser Réponse ci-dessous. J'ai essayé de le remplacer par cl-ppcre, mais ce n'est pas simple, donc la fonction ci-dessous était mieux adaptée pour ce travail. – MatthewRock

5

Je pense qu'il n'y a pas une telle fonction dans la norme. Si vous ne voulez pas utiliser une expression régulière (cl-ppcre), vous pouvez utiliser ceci:

(defun string-replace (search replace string &optional count) 
    (loop for start = (search search (or result string) 
          :start2 (if start (1+ start) 0)) 
     while (and start 
        (or (null count) (> count 0))) 
     for result = (concatenate 'string 
            (subseq (or result string) 0 start) 
            replace 
            (subseq (or result string) 
              (+ start (length search)))) 
     do (when count (decf count)) 
     finally (return-from string-replace (or result string)))) 

EDIT: Shin Aoyama a souligné que cela ne fonctionne pas pour remplacer, par exemple, "\"" avec "\\\"" en "str\"ing". Depuis que je considère maintenant ce qui précède comme assez lourde je propose la mise en œuvre donnée dans le Common Lisp Cookbook, ce qui est beaucoup mieux:

(defun replace-all (string part replacement &key (test #'char=)) 
    "Returns a new string in which all the occurences of the part 
is replaced with replacement." 
    (with-output-to-string (out) 
    (loop with part-length = (length part) 
      for old-pos = 0 then (+ pos part-length) 
      for pos = (search part string 
          :start2 old-pos 
          :test test) 
      do (write-string string out 
          :start old-pos 
          :end (or pos (length string))) 
      when pos do (write-string replacement out) 
      while pos))) 

Je aime particulièrement l'utilisation de with-output-to-string, qui effectue généralement mieux que concatenate.

+0

Bien que la dernière implémentation se bloque si * part * est la chaîne vide. Il devrait vérifier pour cela, pour être correct. –