杂记 › 技术笔记 › 复制来的文本全是空行和多余空格?批量清理的顺序

复制来的文本全是空行和多余空格?批量清理的顺序

上周接手一份从 PDF 里抠出来的参考文献清单,180 多条。乍看条目齐全,粘进编辑器打开"显示空白字符"之后全是问题:每行中间夹着排版继承下来的换行,标题里有一整串空格,最前面还躲着一个完全看不见的字符,害得第一条和最后一条在排序时跑到莫名其妙的位置。我原本打算一条条手删,删到第 40 条就乱了套——因为我第一个动作是"删除所有空行",那一批由空格组成的行立刻变成真正的空行,前面已经处理过的内容又开始变。

看不见的字符不止一种

那次让我印象最深的教训是:空白不是"一种东西",它是好几种不同的字符,长得一样但来源和处理方式都不一样。把它们分清,才知道该开哪个开关。

字符 码点与写法 通常从哪来 屏幕上的表现
半角空格 U+0020,代码里 " " 键盘直接敲的 窄空白,肉眼最容易认
全角空格 U+3000 中文排版、中文输入法下打出的空格 约一个汉字宽
不换行空格 U+00A0,HTML 里常写成   网页里的缩进与"别在这里断行"的间隔 看着和普通空格一样,但会参与字数
制表符 Tab,U+0009,代码里写 \t Excel 复制时的列分隔、代码缩进 跳到下一个制表位,宽度不定
换行符 LF U+000A 即 \n,CR U+000D,Windows 常见 CRLF 行尾;PDF 的每一行排版都会留下痕迹 把一条记录切成多行
BOM U+FEFF,UTF-8 下字节是 EF BB BF 某些编辑器存盘时加在文件开头 完全看不见,只让首行变形

从 C:\Users\name\a.txt 这种路径组成的列里复制出来,问题往往是复合的:列之间是 Tab,行末是 CRLF,路径本身还带反斜杠。这时候"删空格"这种笼统动作完全没意义,得指名道姓。

顺序为什么会影响结果

清理不是幂等的,前一步会改写后一步的输入。我踩过的三个具体坑:

全角空格转半角必须放在去空格之前。如果先把半角空格删干净,再去做全角转半角,转出来的那批新空格就躲过了上一轮,文本里留下一堆看起来"删过了却还在"的空白。

去空行要放在首尾清理之后。由空格或 Tab 组成的行,在工具眼里并不是空行,它里面有两个字符。先删每行首尾空格,这些行会立刻塌成零长度,下一轮去空行才删得掉。我做反的那一次,正是先删空行,结果空行数字纹丝不动,我以为开关没生效。

去除所有换行必须是最后一步。因为"每行首尾"这个概念在合并成一行之后就不存在了。多行合一以后再去 trim,作用对象是整段的两端,中间那些原本在行尾的空格全留在原地。

至于"去除所有空格",我把它归到危险动作:代码缩进、Markdown 的对齐、以及从 Excel 复制来的列分隔都是靠空格活着的,全删一次就把一列数据粘成一坨。需要它的时候我先拿十行做小样。

我现在固定的流程

  1. 打开显示空白字符,先确认对手是哪一种。这一步不跳过,否则后面全是猜。
  2. 全角空格转半角。
  3. 去除制表符(要保留列结构时改成先转成空格,别直接删)。
  4. 去除每行首尾空格。
  5. 合并连续空行为一个,或者完全去除空行——按需要选一个,两个都开容易把该留的分隔也吃掉。
  6. 核对统计数字。文本清理 处理时统计会实时跟着变,行数差应当等于我预期删掉的空行数,对不上就回头查前一步。
  7. 确认没有隐形字符残留:  对应的 U+00A0 不在上面任何开关的管辖范围里,我一般会专门看一遍。

清理之后才轮到结构化操作。要给每条加序号和前缀,我用 文本行操作;要把这份清单和另一份比对、或者按字序排一遍去掉重复条目,用 文本排序去重。顺序固定是"先清理后运算",因为尾随空格会让两个明明相同的条目被判成不同,去重结果直接失真。

有一类问题清理解决不了

那份文献清单最后还剩两条没救回来:PDF 排版把一条记录从中间分页切断,第二条的作者名被劈成上下两半。删空行只能删字符,不知道哪两个半行本来是一句话。

我的处理办法是手工把它们拼回去,然后接受"这一步必须人来"。同类情况还有断词连字符,PDF 里 com- 换行 puter 这种,把换行删掉之后得到 com-puter,还是错的,得连字符一起删。这类问题属于内容被切碎,不属于字符多余。

Q:为什么删了空行,导出还是有一堆空行?

因为那些行不是空的,里面有空格或 Tab。先去每行首尾空格,让它们塌成真空行,再执行去空行;顺序换一下就删不掉。

Q:从 Excel 复制一列路径,粘出来变成一坨,怎么回事?

Excel 用 Tab 分隔列、用 CRLF 分隔行。想保留一行一条就只处理行、把 Tab 换成你要的分隔符;想保留表格结构就别动 Tab。

Q:首行开头有个字符删不掉,怎么办?

那是 BOM(U+FEFF),属于编码层的问题,文本清理里没有对应的开关。我一般重新按无 BOM 的编码另存一次,而不是拿删除字符去硬磕。

Q:一次性勾全部清理选项,不是更省事?

省事但不可控。全角转换和去空格互相制造对象,去空行和 trim 互相依赖,全部勾上之后统计数字变了你也不知道是谁变的。我宁可分两三轮,每轮只开一两个开关,看统计确认效果。

Q:清理会把正文里的字删少吗?

选项本身只针对空白字符和标签,不该动到正文。但"去除所有空格"和"去除 HTML 标签"这两项威力大,处理带中英混排或带标记的内容时,我一定先拿一小段验证,再整批做。

回到那份清单:180 多条清理完剩 178 条,少的两条是我手工拼回去的。我最终记住的不是某个开关的位置,而是这条判断——空白字符的问题先分类再排序,顺序错了,同一批选项会做出完全不同的结果;而内容被排版切碎的部分,工具帮不上,别指望多勾一个选项能补回来。

📎 相关文章

排版稿没内容可填?占位文本怎么写才不像模板 2026-10-15 两列数据要列出所有组合?分列合并与笛卡尔积 2026-10-15 测试上传限制要多大文件?按需造一个指定大小的 2026-10-15 几十MB的文本发不出去也打不开?按行数切小 2026-10-15 只要文件名不要路径?几百行路径批量提取 2026-10-15