# 4.3 创建字符串

本章将介绍 直接，间接（如拼接，取子字符串）创建字符串的函数。至于通过修改其他字符串内容，从而创建新字符串的方法，请查阅 搜索与替换 章节。

Function: make-string count character & optional multibyte\
&#x20; 这个函数将 character 重复 count 次，并作为字符串返回。如果 count 为负，那么这个函数会抛出错误。

```
(make-string 5 ?x)
    => "xxxxx"
(make-string 0 ?x)
    => ""
```

通常来说，如果一个字符是ASCII字符，那么返回的字符串是单字节字符串。如果可选参数 multibyte 非nil，则函数会返回一个多字节字符串。如果后面，你需要拼接非ASCII字符串或使用非ASCII字符替换其中字符的话，这个这个功能会非常有用。

其他还有些类似的函数，比如 make-vector （查阅向量章节）和 make-list （查阅列表构造章节）

Function: substring string \&rest characters\
&#x20;这个函数返回一个包含字符characters的字符串。

```
(string ?a ?b ?c)
    => "abc"
```

Function: substring string \&optional start end\
&#x20; 这个函数从 string 中抽取某一范围的字符，并将这些字符构造成字符串返回。范围由可选参数 start 和 end 决定。其中字符串的第一位的索引为 0.如果只有一个参数，那么这个函数就会拷贝整个 string。

```
(substring "abcdefg" 0 3)
    => "abc"
```

在上面的例子中， "a" 的索引为 0，"b" 的索引为 1，"c" 的索引为2.而索引3，也就是字符串中的第四个字符的位置，标注了子字符串终止的位置。因此，"abc" 便从原来的 "abcdef" 中拷贝出来。

这个函数同时也支持负的索引，比如 -1 表示字符串的最后一个字符。举个例子：

```
(substring "abcdefg" -3 -1)
    => "ef"
```

在这个例子里，"e" 的索引为 -3，"f" 的索引为 -2，而 "g" 的索引为 -1.因此，"e" 和 "f" 都被包括，但 "g" 被排除在外。

如果 end 为 nil，那么就默认到字符串结尾，因此，

```
(substring "abcdefg" -3 nil)
    => "efg"
```

end 参数缺失和将end设为 nil 是等价的。(substring string 0) 就会返回一整个string的拷贝。

```
(substring "abcdefg" 0)
    => "abcdefg"
```

但是如果是想拷贝整个字符串，我们更推荐使用 copy-sequence（详情查阅 序列函数）。

如果字符串中有的字符具有文本属性，那么文本属性也会被一并拷贝到新的字符串中。详情查阅 文本属性。

函数 substring 同时也可以处理向量。比如：

```
(substring [a b (c) "d"] 1 3)
    => [b (c)]
```

如果 start 不是整数，或者 end 既不是整数，也不是 nil。那么这个函数会抛出 wrong-type-argument 错误。如果 start 标记的位置在 end 之后，或其中有参数超出了字符串范围，那么函数会抛出 args- out-of-range 错误。

另外有一个函数 buffer-substring，用来从当前缓冲区中拷贝子字符串。不过这个函数作用的是缓冲区，而缓冲区的起始索引为 1，而非字符串的 0.

Function: substring-no-properties string \&optional start end\
&#x20; 这个函数和 substing 很相似，但是这个函数并不拷贝文本属性。此外，对于这个函数 start 为 nil，和start 为 0 是等价的。因此，这个函数返回一个无文本属性的字符串。

Function: concat \&rest sequences\
&#x20; 将 sequences 中所有的字符拼接在一起，然后返回（包括文本属性）。其参数必须是字符串、数字列表、数字向量；而参数本身并不会被修改。此外如果 concat 没有收到任何参数，那它就会返回一个空字符串。

```
(concat "abd" "-def")
    => "abc-def"
(concat "abc" (list 120 121) [122])
    => "abcxyz"
;; nil 表示空列表
(concat "abc" nil "-def")
    => "abc-def"
(concat "The" " quick brown " "fox.")
    => "The quick brown fox."
(concat)
    => ""
```

但要记住，这个函数并不总是返回新创建的字符串。调用者需要知道这一点。此外，也不也不要使用 eq 来将其和已存在的字符串进行比较。

因为实际上，返回的字符串可能隐形的改变了参数中的字符串，因此可能会引发潜在的 错误。为了获取绝对安全的字符串，你最好在其返回的字符串上再调用一个 copy-sequence。

你可以在 Mapping函数章节 查看 mapconcat，在 Vector函数章节 查看 vconcat，在 列表构建章节 查看 append。他们其他的拼接函数。对于拼接命令行参数这样的特定工作，请查阅 合并和引用字符串章节。

Function: split-string string \&optional separators omit-nulls trim\
&#x20; 这个函数用来根据分隔符，对string进行分割。其中的分隔符可以为正则表达式（详情查阅正则表达式章节）。所有被正则表达式匹配到的字符都会被当作分隔符；分隔后的子字符串们会以字符串列表的形式返回。

如果参数 separators 为 nil（或缺失），那么默认的分隔符就取决于变量 splite-string-default-separators 。而且参数 omit-null 会默认设置为 t 。

如果参数 omit-nulls 为 nil（或缺失），那么返回的结果将会包含 null 字符，如果该参数为 t，那么 null 字符便会从结果中移除。

如果可选参数 trim 非 nil，那么它必须为正则表达式，而这个正则表达式会对分隔的字符串列表中的每一个子字符串进行匹配。如果匹配结果为空，那么这个子字符串会被当成 null 处理。

如果你将独立的命令行参数分隔开，那么为了配合 call-process 或 start-process 函数，你需要查阅 分隔字符串和解引用章节。

比如:

```
(split-string " two words ")
    => ("two" "words")
```

结果并非 ("" "two" "words" "")。如果你需要这样的结果，那你需要显式地声明分隔符：

```
(split-string " two words "
                split-string-default-separators)
    => ("" "two" "words" "")
```

```
(split-string "Soup is good food" "o")
    => ("S" "up is g" "" "d f" "" "d")
(split-string "Soup is good food" "o" t)
    => ("S" "up is g" "d f" "d")
(split-string "Soup is good food" "o+")
    => ("S" "up is g" "d f" "d")
```

TODO
