连字符与破折号
文本中用于连接单词、表示范围、分隔插入语等的横线符号。连字符、半角破折号 (en dash) 和全角破折号 (em dash) 外观相似,但在 Unicode 中是不同的字符,UTF-8 下的字节数也不同。
连字符与破折号是一组外观相似但用途各异的横线符号,在日常使用中极易混淆。Unicode 对它们做了明确区分:连字符减号 (U+002D)、连字符 (U+2010)、半角破折号 (U+2013)、全角破折号 (U+2014)、水平线 (U+2015) 等,多种横线字符各有定义。各自用途不同,正确区分使用直接关系到排版的质量。
连字符减号 (U+002D) 是 ASCII 中唯一的横线字符 (属于 Unicode 常规类别 Pd),可以直接从键盘输入。在编程中它充当减号运算符,在 URL 和文件名中用作单词分隔符。它本是一个兼顾连字符和减号功能的折中字符,但在实际使用中,绝大多数场景都由这一个字符覆盖。虽然另有一个表示纯粹连字符的 U+2010,但它输入不便、外观又无区别,实际上几乎无人使用,U+002D 成了事实上的标准。
半角破折号 (U+2013) 用于表示范围 (如"1990 年至 2000 年""第 10 至 20 页") 或对等两者的对比与连接。全角破折号 (U+2014) 用于分隔插入语或表示话语中断。它们的名称源自活字的宽度:半角破折号 (en dash) 约为小写字母"n"的宽度,全角破折号 (em dash) 约为大写字母"M"的宽度,因此后者更长。英文出版物严格遵守这一区分,但网页和日常文本中多用连字符减号代替。仅凭字面很难判断究竟是哪个字符,存疑时应确认码位:Python 用 hex(ord(ch))、JavaScript 用 ch.codePointAt(0).toString(16),连字符减号返回 0x2d / 2d,半角破折号返回 0x2013 / 2013。
在中文排版中,破折号的使用遵循 GB/T 15834《标点符号用法》。中文破折号由两个全角破折号 (U+2014) 连用构成,占两个汉字的宽度,用于标示注释内容、话题转换或声音延长。需要注意的是,中文破折号中间不能断开,这一点与英文 em dash 的用法有所不同。此外,中文里还会用到连接号来连接起讫的地点或时间等相关项目:GB/T 15834 规定的连接号形式是短横线、一字线 (与 em dash 同码位,U+2014) 和浪纹线,全角连字符 (U+FF0D) 并不是规范的连接号形式。
在处理文本时,全角破折号还有一个避不开的陷阱。Shift_JIS 的 0x815C 究竟对应哪个 Unicode 字符,各家实现并不一致:微软 CP932 系的转换表把它映射为水平线 (U+2015),而 JIS 规格和苹果系的转换则映射为全角破折号 (U+2014)。因此,若遇到只有全角破折号变成别的记号或"?"的文本,首先应怀疑这种映射上的分歧。另外,日文长音记号"ー"(U+30FC) 和全角连字符减号 (U+FF0D) 因字形相近,也容易与破折号混淆。它们本是表示长音和连字符的不同字符,若拿来代替破折号,在检索、替换和排序时就会被当作不同的字符处理。
从字符计数的角度看,这些横线字符虽然都算作 1 个字符,但字节数各不相同。连字符减号 (U+002D) 在 UTF-8 编码下占 1 个字节,半角破折号 (U+2013) 和全角破折号 (U+2014) 则占 3 个字节。在基于字节数的字符限制场景中,不同种类的横线符号消耗的字节数差异值得关注。
在编程领域,连字符减号能否用于标识符取决于具体语言。CSS 的类名和属性名允许使用连字符 (kebab-case),但 JavaScript 的变量名不允许。至于 URL 的路径部分,Google 推荐用连字符而非下划线来分隔单词,理由是连字符分隔更便于用户和搜索引擎切分 URL 中的词,而下划线历来在编程中用于表示"一个整体的名称"。不过这只是关于抓取和易读性的建议,并不意味着改用连字符就能提升排名。域名中同样可以使用连字符,但不能置于标签的首尾。