我有一个“/node/143”形式的查询请求-uri(只是格式的示例)。
我想从字符串中删除第一个正斜杠,我查找了函数 删除并尝试了一下。 我似乎无法让它工作(我在 Linux 上使用 SBCL)。
我已经使用此代码设置了 request-uri。
(setq request-uri "/node/143")
当我检查变量时,我返回了这个变量。
request-uri
"/node/143"
我现在尝试删除第一个斜杠(此时只需查看该函数如何正确使用即可)。
(remove "/" request-uri)
"/node/143"
(remove '/ request-uri)
"/node/143"
我什至尝试提供一个列表
(remove '("/") request-uri)
"/node/143"
(remove '('/) request-uri)
"/node/143"
即使字符串是 向量字符 我认为不知何故,整个字符串可能会放在一个单元格中,我尝试删除整个字符串,但仍然没有运气。
(remove "/node/143" request-uri)
"/node/143"
(remove '/node143 request-uri)
"/node/143"
所以我现在很茫然,这个看似简单的功能确实让我困惑,我以为我严格按照文档进行操作,但没有任何效果。
谁能解释一下这里发生的事情吗?
谢谢。
编辑:我找到了问题的答案,这又提出了另一个问题。
要从我使用的字符串中删除元素,
(remove #\/ request-uri)
整个字符串怎么样?
`(remove #\node request-uri`)
仅适用于第一个字符和抛出一个错误,下面的一切都不做。
(remove "node" request-uri)
(remove 'node request-uri)
(remove ?\node request-uri)
(remove #\node request-uri)
(remove '("node") request-uri)
我不确定这里还应该如何解决。
I have a query request-uri in the form of "/node/143" (just an example of the format).
I want to strip the first forward slash from the string, I looked up the function remove and had a try. I just can't seem to get it working (I'm using SBCL on Linux).
I've set the request-uri using this code.
(setq request-uri "/node/143")
When I check the variable I have this returned.
request-uri
"/node/143"
I now try to remove the first slash (at this point it's just anything at all to see how the function is properly used).
(remove "/" request-uri)
"/node/143"
(remove '/ request-uri)
"/node/143"
I even tried supplying a list
(remove '("/") request-uri)
"/node/143"
(remove '('/) request-uri)
"/node/143"
Even though strings are vectors of characters I thought that somehow maybe the whole string may be placed in one cell and I tried to remove the whole thing, still no luck.
(remove "/node/143" request-uri)
"/node/143"
(remove '/node143 request-uri)
"/node/143"
So I'm at a loss right now, this seemingly simple function has really eluded me, I thought I followed the documentation to the letter, but nothing is working.
Can anyone shed some light on what's happening here?
Thanks.
Edit: I found the answer to my question, which raised another question.
To remove an element from the string I used
(remove #\/ request-uri)
What about a whole string
`(remove #\node request-uri`)
Only works for the first character and throws an error, and the following all do nothing.
(remove "node" request-uri)
(remove 'node request-uri)
(remove ?\node request-uri)
(remove #\node request-uri)
(remove '("node") request-uri)
I'm not sure how else it should be addressed here.
发布评论
评论(4)
学习阅读 Common Lisp HyperSpec。
字符串是 序列、数组(字符的一维向量),以及,字符串。 这意味着大多数功能都是适用的。
让我们看一下删除。 CLHS 给出了这样的签名:
字符串是字符序列。 因此,对删除的调用将是:
或(例如)
记住:
#\a
是一个字符。#\node
不是字符。 非法的。 字符串是“/foo/”
。要从字符串中删除的项目必须是字符。 没有其他的。 为什么? 因为默认情况下 TEST 是 EQL,并且 EQL 会将字符串中的字符与项目参数进行比较。 默认情况下,密钥也是 IDENTITY,并且不会更改项目。
如果你的参数是一个字符串怎么办? 好吧,那么您必须做更多的事情:
这会查看序列中的每个字符并将其放入字符串中。 然后,将使用 EQUAL 函数将该字符串与您的项目
"/"
进行比较。 这也有效。 代价是它需要将"/abc/"
的每个字符生成一个字符串,每个字符串都是一个新的对象。另一种方法是:
上面在每个测试中检索
"/"
的第一个字符,并将其与字符串"/abc/"
中的字符进行比较。 同样的代价是它需要获得角色五次(在本例中)。因此,如果您的原始对象以字符串形式出现,则最好的编写方式是:
上面我们从字符串
"/"
中获取字符一次,然后 REMOVE 将此字符与默认的 EQL 测试与中的每个字符进行比较字符串 - 它返回一个新字符串,其中包含那些不属于#\/
的 EQL 的字符。你期望什么?\foo 是什么? 在 Common Lisp 中,这是符号
|?fOO|
。而且
(remove "foo" "afoob")
不起作用,因为字符串(此处为"foo"
)不是字符串的元素。 请记住,字符是字符串的元素。 另请记住,具有诸如"/"
之类的一项的字符串仍然是字符串而不是字符。 因此"/"
和#\/
是不同的类型。 第一个是字符串,第二个是字符。SUBSEQ 从序列中提取序列。 这意味着它还从另一个字符串中提取一个字符串:
CONCATENATE 附加序列。 这意味着它还附加字符串。
要删除字符串的一部分,另请参见函数 STRING-TRIM、STRING-LEFT-TRIM 和 STRING-RIGHT-TRIM。
因此,正如在另一个答案中从字符串中删除子字符串一样,您需要编写一些代码来提取一些字符串,然后将它们连接起来。
SEARCH 在字符串中搜索字符串。
Learn to read the Common Lisp HyperSpec.
Strings are Sequences, Arrays (one-dimensional vectors of characters) and, well, Strings. This means that most of those functions are applicable.
Let's look at REMOVE. CLHS gives this signature:
Strings are sequences of characters. So a call to remove would be:
or (for example)
Remember:
#\a
is a character.#\node
is no character. Illegal. A string is"/foo/"
.The item to REMOVE from a string has to be a character. Nothing else. Why? Because the TEST is by default EQL and EQL compares the character in the string with your item argument. Also key is by default IDENTITY and does not change the items.
What if your argument is a string? Well, then you have to do more:
This looks at each character of the sequence and makes it into a string. The string then will be compared with your item
"/"
using the function EQUAL. This works also. The cost is that it needs to generate a string from each character of"/abc/"
, each string is a new object.Another way to do it is:
Above retrieves the first character of
"/"
in every test and compares it with the character from the string"/abc/"
. Again the cost is that it needs to get the character five times (in this example).So the best way to write it if your original object comes as a string:
Above we get the character from the string
"/"
once and then REMOVE compares this character with the default EQL test with each character in the string - it returns a new string of those characters that are not EQL to#\/
.What do you expect ?\foo to be? In Common Lisp this is the symbol
|?fOO|
.Also
(remove "foo" "afoob")
does not work since a string ("foo"
here) is not an element of a string. Remember, characters are elements of strings. Remember also that strings with one item like"/"
are still strings and not a character. Thus"/"
and#\/
are of different type. The first is a string and the second is a character.SUBSEQ extracts a sequence from a sequence. That means it also extracts a string from another string:
CONCATENATE appends sequences. This means that it also appends strings.
To remove parts of a string see also the functions STRING-TRIM, STRING-LEFT-TRIM and STRING-RIGHT-TRIM.
So, as in one other answer to remove substrings from a string you need to write some code to extract some strings and then concatenate those.
SEARCH searches for strings in strings.
要删除整个子字符串,您必须创建一个新函数,例如:
这只是一个起点。 我复制了“搜索”的所有选项,但我认为某些选项在这种情况下没有意义。 至少这是可行的:
对于更复杂的情况,您也许应该看看 cl-ppcre,一个正则表达式库。
To remove a whole substring, you will have to make a new function, e.g.:
This is just a starting point. I replicated all options for SEARCH, but I think that some options don't make sense in this context. At least this works:
For more elaborate cases, you should perhaps take a look at cl-ppcre, a regex library.
解释:
它们分别是:一个字符串、一个(带引号的)符号、一个(求值的)符号、一个格式错误的字符文字以及一个包含一个字符串的列表。 REMOVE 从对象序列中删除对象,并且字符串不是这些东西的序列。
如果您只想删除字符串的一部分,SUBSEQ 可能可以解决问题:
对于更复杂的事情,您可能需要像 cl-ppcre 和/或 split-sequence 这样的库。 (如果您使用 Hunchentoot,则已经加载了前者。)
Explanation:
These are (respectively): a string, a (quoted) symbol, an (evaluated) symbol, a malformed character literal, and a list containing one string. REMOVE removes an object from a sequence-of-object, and a string is not a sequence of any of these things.
If you just want to remove part of the string, SUBSEQ might do the trick:
For more complex things, you probably want a library like cl-ppcre and/or split-sequence. (If you're using Hunchentoot, you already have the former loaded.)
这会失败,因为“/”是字符串,而不是字符。
如果需要该字符,则需要使用#/,即正斜杠字符。
但正如您所看到的,它将删除所有正斜杠。 根据您链接的文档页面,删除需要一个名为 :count 的关键字参数,它表示要删除的项目数。 所以你可以这样做。
希望这可以帮助。
::编辑::
这不是?/,而是#/。 谢谢道格拉斯!
This fails because "/" is a string, not a character.
If you want the character, you need to use #/ i.e. the forward slash character.
But as you can see, it'll remove all forward slashes. According to doc page you linked, remove takes a keyword param named :count, which says how many items to remove. So you could do this.
Hope this helps.
::EDIT::
It's not ?/, it's #/. Thanks Douglas!