Question

Je demande-uri requête sous forme de "/ node / 143" (juste un exemple du format).

Je veux enlever la première barre oblique de la chaîne, je regardais la fonction remove et a essayer. Je ne peux pas sembler pour le faire fonctionner (j'utilise SBCL sous Linux).

J'ai mis la demande-uri en utilisant ce code.

(setq request-uri "/node/143")

Quand je vérifie la variable que j'ai ce retour.

request-uri
"/node/143"

Je vais maintenant essayer d'enlever la première barre oblique (à ce stade, il est tout simplement rien du tout pour voir comment la fonction est utilisée correctement).

(remove "/" request-uri)
"/node/143"

(remove '/ request-uri)
"/node/143"

J'ai même essayé fournir une liste

(remove '("/") request-uri)
"/node/143"

(remove '('/) request-uri)
"/node/143"

Même si les chaînes sont vecteurs de caractères Je pensais que peut-être en quelque sorte la chaîne entière peut être placée dans une cellule et j'ai essayé d'enlever le tout, toujours pas de chance.

(remove "/node/143" request-uri)
"/node/143"

(remove '/node143 request-uri)
"/node/143"

Je suis donc à une perte en ce moment, cette fonction apparemment simple m'a vraiment échappé, je pensais que je suivais la documentation à la lettre, mais rien ne fonctionne.

Quelqu'un peut-il faire la lumière sur ce qui se passe ici?

Merci.

Edit:. J'ai trouvé la réponse à ma question, qui a soulevé une autre question

Pour supprimer un élément de la chaîne I utilisé

(remove #\/ request-uri)

Qu'en est-il une chaîne entière

`(remove #\node request-uri`)

ne fonctionne que pour le premier caractère et renvoie une erreur, et après tout ne rien faire.

(remove "node" request-uri)
(remove 'node request-uri)
(remove ?\node request-uri)
(remove #\node request-uri)
(remove '("node") request-uri)

Je ne sais pas comment le reste devrait être abordée ici.

Était-ce utile?

La solution

Apprendre à lire Common Lisp hyperspec .

Les chaînes sont Sequences, tableaux (vecteurs à une dimension de caractères) et, ainsi, Cordes . Cela signifie que la plupart de ces fonctions sont applicables.

Regardons RETIRER . CLHS donne cette signature:

remove item sequence &key from-end test test-not start end count key
    => result-sequence

Les chaînes sont des séquences de caractères. Donc, un appel à retirer serait:

(remove #\/ "/foo/")

ou (par exemple)

(remove #\/ "/foo/" :start 2)

Souvenez-vous: # \ a est un personnage. # \ Noeud est pas de caractère. Illégal. Une chaîne est « / foo /".

L'élément à supprimer à partir d'une chaîne doit être un caractère. Rien d'autre. Pourquoi? Parce que le test est par défaut EGL et EGL compare le caractère de la chaîne avec votre argument article. Un autre élément clé est par défaut IDENTITÉ et ne change pas les éléments.

Que faire si votre argument est une chaîne? Eh bien, alors vous devez faire plus:

 (remove "/" "/abc/" :key #'string :test #'equal)

regarde chaque caractère de la séquence et en fait une chaîne. La chaîne sera ensuite comparée à votre article « / » en utilisant la fonction EQUAL. Cela fonctionne également. Le coût est qu'il doit générer une chaîne de chaque caractère « / abc / », chaque chaîne est un nouvel objet.

Une autre façon de le faire est:

 (remove "/" "/abc/" :test (lambda (a b) (eql (aref a 0) b)))

Au-dessus du premier extrait de caractère « / » dans tous les tests et le compare avec le caractère de la chaîne « / abc / ». Encore une fois le coût est qu'il a besoin d'obtenir le caractère cinq fois (dans cet exemple).

La meilleure façon de l'écrire si votre objet original se présente comme une chaîne:

(remove (aref "/" 0) "/abc/")

Au-dessus, nous obtenons le caractère de la chaîne « / » une fois, puis RETIRER compare ce caractère avec le test par défaut EQL avec chaque caractère de la chaîne - il renvoie une nouvelle chaîne de ces personnages qui ne sont pas EQL à # / <. / p>

Qu'est-ce que vous attendez? \ Foo être? Dans Common Lisp c'est le symbole |? FOO |.

En outre (enlever « foo » « afoob ») ne fonctionne pas depuis une chaîne ( « foo » ici) n'est pas un élément d'une chaîne. Rappelez-vous, les personnages sont des éléments de chaînes. Rappelez-vous aussi que les chaînes avec un élément comme « / » sont encore des chaînes et non pas un personnage. Ainsi « / » et # / sont de type différent. La première est une chaîne et le second est un caractère.

subseq extrait une séquence d'une séquence. Cela signifie qu'il permet également d'extraire une chaîne d'une autre chaîne:

(subseq "0123456" 1 5)
     where 1 is the start and 5 is the end index.

CONCATENER ajoute séquences. Cela signifie qu'il ajoute également des chaînes.

(concatenate 'string "abc" "123")
  returns a new string with the strings "abc" and "123" appended.

Pour supprimer des parties d'une chaîne voir également les fonctions STRING-TRIM, STRING-GAUCHE-TRIM et STRING-droite-TRIM.

Alors, comme dans une autre réponse à supprimer chaînes d'une chaîne vous devez écrire un code pour extraire quelques chaînes puis concaténer celles-ci.

SEARCH effectue la recherche des chaînes dans les chaînes.

Autres conseils

Pour supprimer une sous-chaîne entière, vous devrez faire une nouvelle fonction, par exemple:.

(defun remove-string (rem-string full-string &key from-end (test #'eql)
                      test-not (start1 0) end1 (start2 0) end2 key)
  "returns full-string with rem-string removed"
  (let ((subst-point (search rem-string full-string 
                             :from-end from-end
                             :test test :test-not test-not
                             :start1 start1 :end1 end1
                             :start2 start2 :end2 end2 :key key)))
    (if subst-point
        (concatenate 'string
                     (subseq full-string 0 subst-point)
                     (subseq full-string (+ subst-point (length rem-string))))
        full-string)))

Ceci est juste un point de départ. Je répliqués toutes les options pour la recherche, mais je pense que certaines options ne font pas de sens dans ce contexte. cela fonctionne au moins:

(remove-string "node" "this is a node or not")

Pour les cas plus complexes, vous devriez peut-être jeter un oeil à cl-ppcre, une bibliothèque regex.

Explication:

(remove "node" request-uri)
(remove 'node request-uri)
(remove ?\node request-uri)
(remove #\node request-uri)
(remove '("node") request-uri)

Ce sont (respectivement): une chaîne, un symbole (cité), un (évalué) symbole, un caractère littéral malformé, et une liste contenant une chaîne. RETIRER supprime un objet à partir d'une séquence d'objet, et un chaîne n'est pas une suite de l'une de ces choses.

Si vous voulez juste enlever une partie de la chaîne, subseq pourrait faire l'affaire:

(let ((uri "/node/143"))
  (when (string= (subseq uri 0 6) "/node/")
    (format t "user wants node ~D" (parse-integer (subseq uri 6)))))

Pour les choses plus complexes, vous voudrez probablement une bibliothèque comme séquence split-cl ppcre et / ou. (Si vous utilisez Hunchentoot, vous avez déjà l'ancien chargé.)

Cela échoue parce que "/" est une chaîne, pas un caractère.

(remove "/" request-uri)
"/node/143"

Si vous voulez que le personnage, vous devez utiliser # / à savoir le caractère de barre oblique.

(remove #\/ request-uri)
"node143"

Mais comme vous pouvez le voir, il va supprimer tous barres obliques. Selon la page de doc vous LIÉ, supprimer un mot-clé prend le nom param: compter, qui dit le nombre d'éléments à supprimer. Donc, vous pouvez le faire.

(remove #\/ request-uri :count 1)
"node/143"

Hope this helps.

:: EDIT ::

Il est pas? /, Il est # /. Merci Douglas!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top