下划线文本生成器

为每个字符尾部叠加 Unicode 组合字符 U+0332(紧贴版换成 U+0331,上划线换成 U+0305),生成可粘贴到任何输入框的纯文本下划线,并用码点、码元、字素三个口径和实测渲染宽度证明它真的加上了。

原文字素9
输出码点18
输出码元18
组合标记数9
UTF-8 字节45
渲染宽度实测零宽(与原文同宽)
原样渲染预览:柳̲泉̲工̲具̲下̲划̲线̲示̲例̲

输入框里按 Ctrl / Cmd + Enter 生成(Enter 单独按是换行,必须留给它);点「生成下划线」同样触发。「渲染宽度实测」用 measureText 比较加标记前后的宽度:两者相等说明标记是零宽叠加、真的并进了字素;宽度变大说明当前字体把它画成了独立字符,粘贴到部分平台会散开。

使用方法

  1. 在待处理文本框里填要加下划线的内容,默认已经是示例值 柳泉工具下划线示例(9 个字素)。允许 1~5000 字,换行会保留,每一行单独处理。
  2. 选下划线样式:默认「低位下划线」= 每个字符后追加 U+0332(COMBINING LOW LINE,画在字身下方);「紧贴下划线」= 换成 U+0331(COMBINING MACRON BELOW,线更短、更贴近字身);「上划线」= 换成 U+0305(COMBINING OVERLINE,画在字身上方)。
  3. 按 Ctrl/Cmd + Enter 或点「生成下划线」。结果区立刻给出可粘贴的纯文本,同时刷新 6 个指标。
  4. 看渲染宽度实测这一格:显示「零宽(与原文同宽)」说明叠加成功;显示具体变宽了多少像素,说明当前字体没把组合标记并进字素,需要换字体或改用 HTML 写法。
  5. 点「复制结果」把纯文本带走;点「载入示例」把输入框还原成 柳泉工具下划线示例 并重算。

这个下划线文本生成器能解决什么问题

一是在没有富文本的地方给字加下划线。表单里的「重要」、群公告里的「报名截止」、后台备注里的「已核对」,这些输入框既不认 <u> 标签也不认 Markdown,只有纯文本能进去。下划线的本质是把「一条线」也当成一个不可见的字符塞进字符串里,它跟着内容一起被复制、粘贴、存库,不需要目标端做任何渲染支持。

二是把「强调」这份信息写进文本本身。一份从系统导出的清单,如果强调只能靠加粗,导出成 CSV 或贴进聊天就全丢了;用组合下划线,强调跟着字符走,谁打开都能看到下面那条线(除非对方字体缺字形)。

三是核对到底有没有加上。很多人粘出去发现别人看到的还是干净文字,就以为工具坏了。其实字符串里的码点数已经翻倍,只是对方字体缺这个组合字形没画出来。这一页同时给出码点、码元、字素三个数字和实测宽度,能直接区分「没加上」和「加上了但对方没渲染」这两种完全不同的情况。

四是给不同平台挑合适写法。同一句「报名截止」,Unicode 组合下划线是 6 个码点的纯文本,HTML 的 <u> 是 10 个字符、需要目标端按 HTML 渲染,Markdown 根本没有原生下划线语法。选哪种取决于内容最终落在哪里,本页只产出第一种。

这个下划线文本生成器不做删除线(那是 U+0336 的长横线叠加,用「删除线文本生成器」);不做上标、粗体、花体那些字形替换(用「特殊字体生成器」「花体文本生成器」);也不做字数与字符数统计,口径分别用「字数统计工具」和「字符数统计工具」看。

原理与规则说明:U+0332 叠加、三口径计数与渲染依赖

算法只有一行:把字符串拆成码点,每个码点后面拼上一个组合标记。代码是 Array.from(s).map(function (c) { return c + UNDERLINE; }).join(''),其中 UNDERLINE 是 '\u0332'。用 Array.from 而不是 s.split('') 是因为后者按 UTF-16 码元切分,会把表情符号这类代理对拆成两个半字符,组合标记插在半个字符中间,输出直接损坏。

三个码位的差别在线的位置和长度,不在有没有线。U+0332 COMBINING LOW LINE(十进制 818)是画得最低、最长的一条下划线,视觉上最接近传统下划线;U+0331 COMBINING MACRON BELOW(十进制 817)是一条较短的横线,位置更贴近字身下缘,适合小字号或行距很挤的场景;U+0305 COMBINING OVERLINE(十进制 773)画在字身上方,用来做上划线。三者都是 Mn 类(非间距标记),按 Unicode 规则不占前进宽度,所以叠加后排版宽度不变。

组合标记必须紧跟基字符,顺序不能颠倒。正确写法是 基字符 + 组合标记,例如 下 后面跟 U+0332;反过来把 U+0332 放在最前面,它找不到可叠加的基字符,浏览器要么画成一个独立的空白占位,要么直接丢弃,整串文本看起来毫无变化但码点已经变了。这也是本页输出永远以真实字符开头的原因。

组合标记能叠多个。同一个基字符后面可以连跟多个 Mn 类标记,例如同时加 U+0332 与 U+0305,渲染出来就是「上有线、下有线」。本页为保持输出稳定,每次只叠一个标记、且固定顺序,不做随机排序;需要复叠时把输出的文本再喂回本页选另一种样式即可。

三个口径分别回答三个问题。码点(Array.from(s).length)回答「字符串里到底有没有标记」;码元(s.length)回答「数据库字段和 varchar 长度会涨到多少」;字素(Intl.Segmenter 的 grapheme 粒度,或用「非 Mn 类码点计数」等价实现)回答「人眼看到几个字」。示例串 柳泉工具下划线示例 加低位下划线后是 18 个码点、18 个码元、9 个字素、9 个组合标记,UTF-8 字节从 27 涨到 45。宽度没变而码点翻倍,就是这个工具生效的标准状态。

为什么用实测渲染宽度判断生效,而不是靠肉眼。组合标记按 Unicode 规则不占前进宽度,所以 measureText(加标记后的串).width 与 measureText(原串).width 相等才是正常结果——这一条能反过来证明标记是「叠加」而不是「插入了一个独立字符」。如果宽度明显变大,说明当前字体没有对应的叠加字形,浏览器用了备用字形的独立占位,这种情况下粘贴到别的平台会散成乱码,应当改用 <u> 这类富文本写法。肉眼看不看得见不作为判据,因为字体、字号、缩放都会影响观感。

完整示例(数值仅作演示)

示例条件与页面打开时的默认值完全一致:待处理文本 = 柳泉工具下划线示例(9 个字素),样式 = 低位下划线(U+0332)。下划线文本生成器输出的是纯文本,长度账目按「字素 × 2」放大,实测结果如下:

下面是默认示例的真实输出,可以直接复制出去对照:

柳̲泉̲工̲具̲下̲划̲线̲示̲例̲

同一个输入换成常见内容时,长度按「单层 = 字素 × 2(码点)、字素 × 2(标记数)」线性放大,下表前 12 行默认显示,点「加载更多」展开剩余 4 行:

输入示例字素数单层码点UTF-8 字节粘贴备注
已下线3615常规可用
下划线3615常规可用
备注2410常规可用
A123单字母也会被叠加
OK246拉丁字母覆盖良好
20264812数字同样可用
v2.04812点号也会被叠加
旧价 9951019空格被叠加时线会断开
柳泉工具4820汉字各占 3 字节
重点标注4820常规可用
待确认3615常规可用
草稿2410常规可用

输入范围与对照表

输入框与样式选择项的范围、超限动作如下,右列是填错时结果区会显示的具体提示:

字段/情况允许范围超限或填错时的动作
待处理文本1~5000 个字素,必填空文本拒绝计算并提示「不能为空」;超过 5000 字素拒绝并报出实际字数
下划线样式low / macron / over 三选一下拉框只能选预设项;值异常时回落到低位下划线并提示
纯空白输入不视为有效内容只有空格或换行时拒绝,提示「只有空白,没有可加下划线的字符」
单独的组合标记不单独处理输入里已有孤立 U+0332 时保留原样,不重复叠加
表情与代理对按码点处理,不按码元切不报错;输出会把标记放在整段 emoji 之后
换行保留按行拆分处理,\n 本身不加标记
超长文本上限 5000 字素拒绝;输出 10000 个码点再放大就影响交互

下划线有五种写法,同样是「已下线」这三个字(3 个字素),字符长度与生效条件完全不同:

写法字符长度生效条件适用位置
Unicode 组合下划线(本页)6 个码点纯文本,任何输入框聊天、昵称、表格单元格、数据库字段
纯文本下划线字符拼接 _已下线_5 个字符纯文本,但线是独立字符文件名、变量名、需要真实下划线的场景
Markdown _已下线_无原生下划线语法CommonMark 里当作斜体,GFM 也不支持下划线只能用内联 HTML,很多渲染器默认禁用
HTML <u>已下线</u>10 个字符内容会被当 HTML 渲染网页正文;HTML5 中语义是「非文本注释」
HTML <ins>已下线</ins>14 个字符内容会被当 HTML 渲染修订稿,语义是「新插入的内容」

边界与渲染依赖说明

常见问题

为什么我粘贴出去看到的是干净文字,下划线不见了?

先看结果区的「输出码点」是不是原文的 2 倍。如果是,说明字符确实加上了,只是对方那一端的字体没有画出叠加字形。这种情况换字体、换应用就能显示;若码点没变,才是没生成成功,请点「生成下划线」重试。判断依据始终看码点,不要只看肉眼。

三种样式 U+0332、U+0331、U+0305 该怎么选?

要「像传统下划线」选 U+0332(低位下划线,线最低最长);行距很挤、字号很小、线总是压到下一行文字时选 U+0331(紧贴下划线,线短且靠近字身);要做数学上划线或强调上方时选 U+0305(上划线)。三者码点、字节数完全一样,只有线的位置和长短不同。

加完下划线后,字数统计怎么变了?

看你用哪种口径。按字素数没变(示例仍是 9),因为组合标记不单独成字;按码点或码元数则翻倍到 18。很多平台的字数统计按码元算,所以加了线的文案在按字数计费的场景(短信、广告投放、昵称长度限制)会多算一倍,务必先核对。需要看纯字素口径请用「字数统计工具」。

为什么输入框里按 Enter 是换行,不是生成?

因为这里处理的是多行文本,Enter 必须留给换行——若照搬单行输入框的写法,用户就没法输入第二行了。所以本页用 Ctrl/Cmd + Enter 触发生成,鼠标点「生成下划线」也一样。页面上单行输入类的工具才用裸 Enter。

HTML 的 u 标签和这个工具到底差在哪?

<u> 是一段标签,只在把内容当 HTML 渲染的地方生效,复制进聊天框、Excel、数据库字段都会变成尖括号原文或直接消失;而且 HTML5 里 <u> 的语义是「非文本注释」(比如标注拼写错误),并不是「强调」。组合下划线是纯文本,任何能收字符的地方都在,代价是长度翻倍、依赖对方字体有对应字形。

Markdown 里为什么写不上下划线?

CommonMark 规范里 _文本_ 是斜体、__文本__ 是粗体,根本没有下划线这个标记;GFM 也没加。想在 Markdown 里出下划线只能内联 HTML <u>,而很多平台(尤其评论框)出于安全默认禁用内联 HTML,于是又回到本页这种纯文本方案。

数据库存得下吗,字段要改吗?

字段类型不用改,但长度要预留。varchar(n) 的 n 通常按字符计,加下划线后占用约 2 倍字符数。示例 柳泉工具下划线示例 原文 9 个字符,加线后是 18 个。若字段刚好卡在长度上限,改价格、状态这类短字段时建议把上限乘以 2 再留一点余量。

能同时加下划线和上划线吗?

可以,同一个基字符后面能连跟多个 Mn 类标记。本页每次只叠一个、保持输出稳定;需要复叠时,把输出的文本再粘回本页、选另一种样式再生成一次,就会得到「下有低位线、上有上划线」的效果——但那时代码点变成 3 倍,粘贴前要用宽度实测确认仍然零宽。

相关工具