快速答案:Notepad++ 删除重复行最快怎么做
Notepad++ 删除重复行最快的方法不用写正则。三步:
Ctrl+Alt+S另存一份副本(注意不是Ctrl+Shift+S,那个是“全部保存”,会把改动直接覆盖回所有已打开的文件)- 光标随便点一下,确保没有选中任何内容,点菜单“编辑 → 行操作 → 删除重复行”
- 完了。全文每个内容只留第一次出现的那一行,散落在文件任何角落的重复都算,不要求相邻
它的结果顺序是“每个内容第一次出现的位置”决定的,原顺序会被打乱。要保序去重走第三章的路 2。
只想给某一段去重,就先选中那几行,同一个命令只处理选区跨到的行。
Ctrl+Z 能撤销。文件大的时候我更倾向关掉重开,别太信撤销。
一、先看清全局:一条“脏数据 → 干净数据”的流水线
我处理脏数据的习惯是先按固定顺序走六道工序,而不是拿到文件就想“该用哪个功能”。顺序错一步,最典型的后果是去重写完发现行数只少了两行,因为行尾空格没清,去重眼里每行都不一样。
六道工序与对应菜单
| 工序 | 干什么 | 菜单路径 | 要写正则吗 |
|---|---|---|---|
| 1 看行尾符 | 确认 CRLF / LF 统一 | 看状态栏;不统一就“编辑 → 行尾符转换”(老一点的中文版叫“档案格式转换”,英文是 EOL Conversion) | 不要 |
| 2 清空白 | 去行尾空格、Tab 混排 | “编辑 → 空白字符操作” | 不要 |
| 3 去空行 | 删真空行和“看着空其实有空格”的行 | “编辑 → 行操作 → 移除空行(含空白字符行)” | 不要 |
| 4 过滤 | 只留下我要的行 | “搜索 → 标记”配合“搜索 → 书签” | 通常一条 |
| 5 去重 | 删重复行 | “编辑 → 行操作 → 删除重复行” | 不要 |
| 6 排序 | 定最终顺序 | “编辑 → 行操作”里的各种排序 | 不要 |
为什么顺序不能乱
第 1 步必须在最前面。 官方手册讲去重和排序时写了同一句话:这些操作假设文件里所有行尾符统一,且与当前文件设置一致。手册给的自查办法是看状态栏,那里显示 Windows (CR LF)、Unix (LF) 还是 Macintosh (CR)。混用行尾符的文件,去重会漏、排序会串。改法见行尾符与 CRLF/LF 转换。
第 2 步要在第 5 步前面。 行尾多一个空格,在去重眼里就是两行不同的数据。北京 和 北京 不算重复。第三章末尾有四查清单。
第 4 步和第 5 步的先后看目的。 先过滤再去重,数据量小跑得快;先去重再过滤,能看出上游吐了多少脏数据。我一般先过滤。
哪些步骤根本不用写正则
六道工序里五道半都能点菜单解决。只有“过滤”通常要写一条规则,而且很多时候普通查找模式填个词就行(填 ERROR,勾书签行,标记全部)。
站内正则替换 15 个实例里有个原则我特别认同:能点菜单就点菜单,点不到才写正则。这篇文章基本就是这句话的展开。
二、编辑 → 行操作:这些命令多数人只用过三个
我问过身边十几个用 Notepad++ 的同事“编辑 → 行操作”里你用过哪几条,答案集中在三个:升序排序行、Ctrl+D、Ctrl+L。剩下那一半,几乎没人点开过。
完整命令清单
按官方手册的编辑菜单章节整理。中文菜单名各版本略有出入,认不准看英文那列。
| 菜单项 | 英文 | 作用范围 | 说明 |
|---|---|---|---|
| 升序 / 降序排序行 | Sort Lines Lexicographically Ascending / Descending | 选区跨到的行,无选区则全文 | 按字符编码逐个比,见第四章 |
| 升序排序行(忽略大小写) | …(Ignore Case) | 同上 | 大小写混排的名单 |
| 升序排序行(区域语言顺序) | …(Locale Order) | 同上 | v8.8.1 新增,中文排序用它 |
| 按整数升序 / 降序 | Sort Lines As Integers Ascending / Descending | 同上 | 解决 “100 排在 2 前面” |
| 按小数升序 / 降序(逗号 / 点号) | Sort Lines As Decimals (Comma) / (Dot) | 同上 | 欧洲用逗号,中美用点号 |
| 按行长升序 / 降序 | Sort Lines By Length Ascending / Descending | 同上 | v8.8.9 新增 |
| 倒序排列 | Reverse Line Order | 选区或全文 | v8.0.0 新增,纯翻转不比较内容 |
| 随机打乱行顺序 | Randomize Line Order | 选区或全文 | 造测试数据 |
| 删除重复行 | Remove Duplicate Lines | 选区跨到的行,无选区则全文 | 全局去重,会清空全文书签 |
| 删除连续重复行 | Remove Consecutive Duplicate Lines | 同上 | 只删紧跟在后面的重复 |
| 移除空行 | Remove Empty Lines | 全文 | 只删零字符的行 |
| 移除空行(含空白字符行) | Remove Empty Lines (Containing Blank characters) | 全文 | 只有空格 / Tab 的行也删 |
| 上移 / 下移当前行 | Move Up / Down Current Line | 当前行或选中行块 | Ctrl+Shift+↑ / Ctrl+Shift+↓ |
| 复制当前行 | Duplicate Current Line | 当前行 | Ctrl+D,v8.6 起忽略选区状态 |
| 删除当前行 | Remove Current Line | 当前行 | Ctrl+L |
| 合并行 | Join Lines | 需跨两行以上的选区 | Ctrl+J,换行换成空格 |
| 拆分行 | Split Lines | 选区或光标所在行 | 按右边界或窗口宽度断行 |
跟空白有关的命令不在这里,在“编辑 → 空白字符操作”,见第六章。
两个去重命令到底差在哪
中文菜单里它们只差两个字,但完全是两回事。
“删除重复行”(Remove Duplicate Lines):官方手册原话是只保留全文中出现多次的整行里的第一个实例,其余全删。关键词是 “anywhere in the active file”,不管相不相邻,内容一样就只留第一行。
“删除连续重复行”(Remove Consecutive Duplicate Lines):只删紧跟在第一个实例后面的重复行。第 1 行和第 500 行内容一样,它一个都不删。
两条是并列关系,从来都是独立的菜单项,不是新旧版本关系。正则替换 15 个实例案例 5 用的是后者,那篇的核心是正则和“排序后删连续”,这里不重复。
官方注记:删除重复行会清空全文书签。 手册里有一句中文互联网上我没见人提过的话:因为实现方式的关系,这个命令会清空当前文件的所有书签。
这对用书签做行过滤的人是暗雷。有一次我先 Mark 出所有含 ERROR 的行打上书签,中途手滑点了一次“删除重复行”,书签全没了,接下来点“删除未标记行”差点把整个文件清空。我的做法是把“删除重复行”放到书签用完之后,或者点之前先另存。
连续去重那条也不干净:它不清空书签,但如果某个带书签的行正好被当成连续重复删掉了,那个书签会留在原来的行号上,也就是说它现在指向原本排在它后面的那一行。行数一多,这种偏移靠肉眼发现不了。
只对选区生效的坑
两个去重命令、所有排序命令,都是“有选区就处理选区跨到的行,没选区就处理全文”。听起来贴心,踩坑率很高。
经典事故:选区多带了一行。 你想去重第 5 到第 10 行,鼠标从第 5 行行首拖到第 10 行,手抖拖到第 11 行最前面一点点,选区末端落在第 11 行第 1 列。这时候选区“跨到”了第 11 行,那行也被纳入去重范围,如果恰好重复就被删了,而你不知道。从上一行行尾开始选,起点那行也会被算进去。
我的习惯是选完看一眼状态栏,或者 Ctrl+G 跳行号配合 Shift+↓ 整行选,不拖鼠标。
另外“移除空行”和“移除空行(含空白字符行)”不认选区,永远作用于整个文档。想只删某一段里的空行,没有内置办法。
三、Notepad++ 删除重复行:不写正则的三条路
Notepad++ 删除重复行有三条不写正则的路。先说边界:用正则删连续重复行、以及“排序 + 删除连续重复行”这套组合拳,正则替换 15 个实例案例 5 讲得很细了,包括为什么只能删相邻的、排序的代价是什么。本章讲它没给的那几条路。
那篇最后留了句话:想既保序又全局去重,得装 Python Script 写五行代码,“这是正则的能力边界,绕不过去”。后半句我不同意。下面路 2 用纯内置功能就能做到,一行插件都不用装。
路 1:内置一键全局去重(不在乎顺序时最快)
适用:名单、字典、配置项、IP 集合这类“顺序无所谓,只要不重”的数据。
操作跟开头快速答案一样:另存 → 不选中任何内容 → “编辑 → 行操作 → 删除重复行”。
要排序的话去重前后各点一次都行。我习惯先排序再去重,重复行挨在一起时跑得更快,上万行能感觉到差别。
结果顺序是什么样? 不是原顺序,也不是排序后的顺序,是“每个内容第一次出现的位置”决定的。文件看着会比较乱。最终要排序就无所谓,不排序就基本没法看。
最终要排序就用路 1,不排序看路 2。只想给某一段去重就先选中那几行,选区边界的坑见第二章。
路 2:保序去重四步法(行号锚定)
我这两年用得最多的一套动作,目标是全局去重,保留每组第一个(原始文件里最早出现的那行),行间相对顺序完全不变。
思路是:给每行钉一个行号当“记忆”,然后放心排序,排完再按行号排回来。
严格说是五步,我把最后两个动作算成一步收尾。
前置:先移除空行,并确认行尾符统一。空行会打乱列操作,行尾符混用会让去重漏内容。
第 1 步:给每行钉上行号
- 光标放到第 1 行行首(
Ctrl+Home) - 按住
Alt+Shift再按↓拉到最后一行,行太多就先Alt+Shift+PageDown翻页。手册还列了第三种:光标放到起点,执行一次“开始/结束列模式选择”(英文菜单是 Begin/End Select in Column Mode,中文名各版本译法不一),再把光标移到终点执行一次。它可以在两次执行之间随便翻页,几万行的文件用这个最省事。基本操作见入门篇的列编辑 Alt+C打开列编辑器,数字区域填初始1、增量1、重复1,把“前导零”打开,确定。这个选项在 v8.5.2 之后叫Leading下拉框,选Zeros;再老的版本是个“前导零”复选框,勾上就行。两种我都见过,都在数字区域里
0001北京
0002上海
0003北京
0004广州
怎么确认选区做对了:直接看 Alt+C 的结果,行号是不是插到了每一行的第 1 列。零宽列选区里一个字符都没有,官方手册对它的定义是“只由贯穿多行的光标组成”(consisting only of a caret extending through multiple lines),界面上通常看不出选中效果,别指望肉眼确认;如果行号只插在第 1 行,说明选区没建起来,按 Esc 重来。
行号宽度按行数定,这一步不能省:9,999 行以内用 4 位(正好 1 万行就得用 5 位),10 万行以内用 6 位。宁可多一位别少。宽度不够时第 10000 行之后的行号会溢出成 5 位,第 4 步“按行号排回”整段错位,而且不报错。
用 5 位的话,后面三步要跟着改:第 2 步列号放第 6 列、第 3 步正则用 {5}、第 4 步删前 5 列。别照抄 4 位的参数。
第 2 步:按内容排序,让重复项挨在一起
关键是排序键只取内容,不含行号。
- 光标放到第 1 行第 5 列(行号后面第一个字符)。4 位行号是第 5 列,6 位是第 7 列
- 同样用
Alt+Shift+↓拉到最后一行,做出零宽列选区 - “编辑 → 行操作 → 升序排序行”
手册的说法是:排序会重排选区覆盖到的所有行,排序键限制在列选区内部;列选区零宽时,每行的键从光标右边第一个字符延伸到行尾。翻成人话,排序键正好是去掉行号后的内容。而且手册明确写了,这种基于列选区的排序是稳定排序,键相同的两行先后顺序不变。
0002上海
0001北京
0003北京
0004广州
注意“上海”跑到最前面了,“上”的字符编码比“北”小。跟按拼音想的完全不一样,第四章说的就是这事。
排完先自查一眼:北京 这一组里两行是 1、3,递增的。递增说明零宽列选区做对了、稳定排序生效了;不递增就是选区歪了,Ctrl+Z 重来。这条自查比看界面有用得多,因为选区本身可能看不见。
某行内容为空时光标会落到行尾,排序键是空串,这类行会聚到最前面。
排序没反应就去看“设置 → 首选项 → 编辑”里把列选择转成多编辑的开关(v8.6 起有),开着会让排序键失效。
第 3 步:删掉每组里多余的行
现在整行是“行号 + 内容”,互不相同,两个内置去重命令都用不了(它们比整行)。这一步用一条正则,只比内容部分:
查找串(4 位行号版)
^(.{4})(.*)(\R.{4}\2)+$
替换串
\1\2
6 位行号就把两个 {4} 都改成 {6}。
\1行号,\2内容,(\R.{4}\2)+匹配一行或多行“换行 + 行号 + 相同内容”- 保留的是每组第一行,也就是行号最小的那行,正是原始文件里最早出现的
- 搜索模式选“正则表达式”;
\R需要 7.9 以上版本,站内正则替换 15 个实例用的也是它 . matches newline千万别勾,勾了.*会跨行
最后一行没有换行符:按理 $ 能匹配到缓冲区末尾,但我没验证过。不放心就在文件末尾敲个回车,跑完再删。
0002上海
0001北京
0004广州
第 4 步(收尾):排回原顺序 + 摘掉行号
- 先按 0 (或点一下正文任意位置),确认第 2 步的零宽列选区已取消。手册说排序不会自动清掉列选区,带着列选区做这一步,排序键又会变回内容,整套方法失效
- “编辑 → 行操作 → 升序排序行”,不要任何选区。行号等宽且排在最前,按字符编码升序就等于按行号数值升序
- 用列编辑(
Alt拖选前 4 列)选中所有行号,按Delete
北京
上海
广州
跟原始文件里第一次出现的顺序一模一样,这就是“保序”的意思。
什么时候不划算:上万行且重复率很低时,第 2 步的列选区排序会慢,第 3 步的正则也有回溯开销。我的经验是几千行以内很顺,几万行明显卡,那时候考虑 Python Script 或者导出到数据库 SELECT DISTINCT。
路 3:按某一列去重
场景:CSV 名单里手机号重复,姓名城市不同,想按手机号去重,保留每个号码第一次出现的那行。
这条路是路 2 的推广,只改第 2 步:排序键从“去掉行号的内容”换成某一列。
1001,张伟,13800138001,杭州,线下活动
1002,李娜,13800138002,北京,官网注册
1003,王强,13800138001,上海,线下活动
- 按路 2 第 1 步钉上等宽行号
Alt拖选手机号那一整列(字段宽度不齐就先在 Excel 里对齐,实在对不齐就退回用正则)- “编辑 → 行操作 → 升序排序行”,排序键就是手机号列,稳定排序保证同号码组内保持原顺序
- 正则删组内多余行,跳过行号和前两列,只比手机号:
^(.{4}[^,]*,[^,]*,)([^,]*)(,.*)(\R.{4}[^,]*,\2,.*)+$
替换串 \1\2\3
- 按行号排回,列编辑删掉行号
诚实讲,第 4 步这条正则已经不算“不用写正则”了,可读性也一般。我只在不方便装插件、又确实要按列保序去重时用它。这类活每周都有就老实写脚本。
两个官方警告:选区内或选区左边有 Tab 字符、或者有多字节字符(中文就是)时,列选区排序结果可能不符合预期。中文 CSV 上做列排序,先确认分隔符是逗号不是 Tab,再用等宽字体看一眼对齐。
去重失败?按顺序查这四项
跑完发现行数没变或只少两三行,别急着怀疑命令坏了,按这个顺序查:
1 大小写。 Error 和 error 是两行。内置去重逐字节比较,不忽略大小写。想忽略先“编辑 → 转换大小写为”统一成小写。
2 尾随空格。 最常见。从 Excel、网页、PDF 复制出来的数据,行尾常挂一两个空格,肉眼看不见,去重看得见。先跑“编辑 → 空白字符操作 → 移除尾随空格”。
3 行尾符混用。 手册在去重那段特别注明:去重假设全文行尾符统一。一半 CRLF 一半 LF 的文件,去重结果会莫名其妙。看状态栏确认,不统一就用“编辑 → 行尾符转换”,原理见行尾符与 CRLF/LF 转换。
4 全角半角。 中文数据的经典坑:, 和 ,、() 和 ()、全角空格(U+3000)和半角空格,字节层面完全不同。从网页或微信粘过来的名单,全角比例高得离谱。查的办法是开“视图 → 显示符号 → 显示空格和 Tab”,全角空格显示成小方块,跟半角的点不一样。
什么时候必须改用正则
需要“按某个模式去重”而不是“按整行去重”时。两行内容不完全一样但属于同一条记录(时间戳不同、ID 不同),只按其中一段判重,内置的比不了。回到正则替换 15 个实例案例 5,把思路改成“捕获要判重的那一段”。
四、排序:为什么 100 会排在 2 前面
用 Notepad++ 排序时我第一次遇到这事,是在排一份端口清单,排完发现 100 在 2 前面、8080 在 443 前面。当时以为是 bug,其实是我选错了排序方式。
原因很简单:默认的“升序排序行”按字符编码逐个比。1 的编码比 2 小,所以 100、1000 全排在 2 前。它不认识数字,只认识字符。
9 种排序变体速查
| 排序方式 | 什么时候用 | 版本 |
|---|---|---|
| 按字符编码(Lexicographically) | 纯英文、或位数相同的纯数字 | 全版本 |
| 忽略大小写(Ignore Case) | 大小写混排,想让 apple 和 Apple 挨一起 |
全版本 |
| 区域语言顺序(Locale Order) | 中文、带重音的欧洲语言 | v8.8.1 新增,官方 changelog 有这条 |
| 按整数(As Integers) | 纯数字列,解决 100 排在 2 前 |
全版本 |
| 按小数(逗号 / 点号) | 欧洲写法 10,234 / 中美写法 10.234 |
全版本 |
| 按行长(By Length) | 找异常行、按长度分组 | v8.8.9 新增,官方 changelog 有这条 |
| 倒序(Reverse Line Order) | 不比较内容,纯翻转行序 | v8.0.0 新增 |
| 随机(Randomize Line Order) | 造测试数据、随机抽样 | 全版本 |
除倒序外每种都有升序降序两条。中文菜单里名字各版本略有出入,认准 Ignore Case、Locale、Integers、Decimals、By Length 这几个词就不会点错。
几条手册里的注记:
- 按整数排序会把 IP 排得比较合理,
8.8.8.8在192.168.0.1前面 - 按整数排序能处理“相同非数字前缀 + 数字”,
xyz9在xyz11前面 - 右对齐数字会被空格坑:
1、10、100、1000按整数排会得到100、10、1、1000。带一个空格前缀的整数排在带两个空格的后面,没空格前缀的1000反而最后。排序前先“移除行首空格”能避开
按列排序:列选区作为排序键,且是稳定排序
第三章路 2 已经用过,单独拎出来是因为值得单独记。
操作:Alt 拖出一个列选区(或零宽列选区)覆盖你想当排序键的那一列,然后点任意一条排序命令。手册说法是:排序会重排列选区覆盖到的所有行,排序键限制在列选区内部;零宽时每行的键从光标右边第一个字符到行尾。
手册明确写了这是稳定排序:两行键相同时先后顺序不变,即使键之外的文本不一样。
用处在哪:一份 CSV 按城市列排序,同一城市内部会保持文件里的原始顺序(比如录入时间)。配合列编辑一起用,这一条能解决不少“看着要写脚本才能干”的活。
中文排序用 Locale Order
最容易踩的坑:用默认“升序排序行”排中文名单,得到的是按字节序排的结果,既不是拼音也不是笔画,看着完全随机。
v8.8.1 加进来的区域语言顺序(Locale Order)就是解决这个的,官方描述是“提供符合语言习惯的字母序排序”,调用 Windows 区域排序规则,中文环境下按拼音排。北京 会排在 上海 前面。
另外两条:
- Locale 排序不受行尾符限制。手册特别注明,除 Locale 外其余排序都假设行尾符统一
- Locale 排序本身是稳定排序,而且会把数字当数字处理,排
第2章和第10章也对
排序依据的是 Windows 控制面板“区域”里的设置。
排序前先统一行尾符
手册在排序那段重复了和去重一样的警告:除 Locale 排序外,排序假设全文行尾符统一且与当前设置一致。查法一样看状态栏,不统一就“编辑 → 行尾符转换”,或右键点状态栏行尾符指示器直接改。原理见行尾符与 CRLF/LF 转换。
动手前先另存
排序不可逆。不是撤销不了,是你不一定记得原顺序是什么。几千行日志排完,你根本看不出它原来什么顺序,而 Ctrl+Z 只能在你意识到错误之前救你。Ctrl+Alt+S 两秒钟的事。
五、行过滤:只留下我要的行
Notepad++ 的行过滤是流水线里唯一常要写规则的一步,但写的东西可以很简单,而且有一条完全不用正则的路。
书签流:一条都不用写
假设要从日志里挑出所有含 ERROR 的行:
Ctrl+F打开查找,切到“标记”标签页- 查找内容填
ERROR(不用勾正则,普通模式够) - 勾选“书签行”
- 点“标记全部”
所有匹配行带上书签,行号左边有蓝色圆点,状态栏告诉你标记了多少行。然后“搜索 → 书签”里有五条命令,组成完整流水线:
| 命令 | 作用 | 什么时候用 |
|---|---|---|
| 复制书签行 | 把标记的行复制到剪贴板 | 提取到新文件(最常用) |
| 剪切书签行 | 剪走标记的行 | 原文件里要删掉它们 |
| 删除书签行 | 删掉标记的行 | 这些行是垃圾 |
| 删除未标记行 | 只留下标记的行 | 反向操作 |
| 反向书签 | 书签取反 | 多轮过滤时用 |
“复制书签行”我用得最多,它不改动原文件,结果放剪贴板,Ctrl+N 新建标签、Ctrl+V 粘贴,原始文件原封不动。
“反向书签”是多条件过滤的关键,但用法不是你想的那样:Mark 会在全文范围内匹配,“书签行”只是把书签加到匹配行上,不会自动做交集。正确做法看下面。
正则流:保留匹配行与删除匹配行
需要按模式过滤时,Mark 里勾“正则表达式”,写一条规则,剩下流程完全一样。
| 目的 | 查找串 | 之后的操作 | |
|---|---|---|---|
| 挑出错误和警告 | `\[(ERROR\ | WARN)\]` | 标记全部 → 复制书签行 |
| 挑出非空行 | ^.+$ |
标记全部 → 删除未标记行 | |
| 挑出长度超 200 的行 | ^.{201,}$ |
标记全部 → 复制书签行 | |
| 挑出含 IP 的行 | \d{1,3}(\.\d{1,3}){3} |
标记全部 → 复制书签行 |
删除未标记行 就是“保留匹配行”,删除书签行 就是“删除匹配行”。名字绕,记住“未标记”三个字就行。更多写法在正则替换 15 个实例。
多条件“且”
Mark 一次只能一个条件,想实现“A 且 B”有两招。
招一:两轮书签取交集。 Mark 条件 A 打书签 → “删除未标记行” → “清除所有书签” → Mark 条件 B 打书签 → “删除未标记行”,剩下的就是 A 且 B。代价是原文件其他内容没了,所以第一步改用“复制书签行”把 A 提取到新标签再做第二轮。
招二:一条正则写两个条件。 用正向预查把“且”塞进一条里,比如“含 ERROR 且含 timeout”:
^(?=.*ERROR)(?=.*timeout).*$
(?=...) 是“这个位置后面必须能匹配到”,两个预查叠起来就是同时满足。语法细节在正则替换 15 个实例。
我一般用招二,一条搞定不用来回倒文件。条件超过三个时正则很难读,换招一。
剪贴板闭环
过滤最后一步很关键:把结果提取到新标签,再在新标签上做二次处理。
动作:标记全部 → 复制书签行 → Ctrl+N → Ctrl+V → 在新标签上去重、排序、加前缀。好处是原文件永远干净,而且新标签行数少,后续操作快得多。复制出来的内容末尾会多一个空行,跑一次“移除空行”就行。
六、清洗四件套:只用内置菜单
这章只讲 Notepad++ 内置菜单能点到的。正则版本(行首空格、空行压缩、全文大小写)在正则替换 15 个实例里,不重复。
空白字符操作命令清单
注意这组不在“行操作”里,在“编辑 → 空白字符操作”。很多教程把它们混写,害人找半天。
| 菜单项 | 英文 | 作用 |
|---|---|---|
| 移除尾随空格 | Trim Trailing Space | 删行尾空格和 Tab |
| 移除行首空格 | Trim Leading Space | 删行首空格和 Tab(别在 Python 文件上跑) |
| 移除首尾空格 | Trim Leading and Trailing Spaces | 两头一起删 |
| 行尾符转换为空格 | EOL to Space | 换行换成空格,等于全文合并成一行 |
| 移除多余空白和行尾符 | Trim Both and EOL to Space | 去首尾空格再合并行。v8.4.9 前叫 Remove Unnecessary Blank and EOL |
| Tab 转空格 | TAB to Space | Tab 换成等价数量空格 |
| 空格转 Tab(全部) | Space to TAB (All) | 所有连续空格合并成 Tab |
| 空格转 Tab(行首) | Space to TAB (Leading) | 只转行首缩进部分 |
“行尾符转换为空格”容易和“行操作”里的“合并行”搞混:合并行只处理选区,行尾符转换为空格作用于整个文档。
一个反直觉的行为:手册说 Trim 类命令作用于“选区所在的行”,即使选区没包含那些首尾空格。一行内容是“几个空格 + words here + 几个空格”,你只选中 words,跑“移除首尾空格”,行首行尾照样被删。
大小写转换 8 种
“编辑 → 转换大小写为”下面有 8 条,不是通常以为的 4 条:
| 菜单项 | 效果(以 hello world 为例) |
快捷键 |
|---|---|---|
| UPPERCASE | HELLO WORLD |
Ctrl+Shift+U |
| lowercase | hello world |
Ctrl+U |
| Proper Case | Hello World |
Alt+U |
| Proper Case (blend) | 同上,但保留已存在的大写 | Alt+Shift+U |
| Sentence case | Hello world |
Ctrl+Alt+U |
| Sentence case (blend) | 同上,但保留已存在的大写 | Ctrl+Alt+Shift+U |
| iNVERT cASE | 逐字母翻转大小写 | 无 |
| ranDOm CasE | 随机大小写 | 无 |
blend 版本的区别值得说:普通 Proper Case 会把 iPhone 变成 Iphone、MySQL 变成 Mysql;blend 版本保留词里已存在的大写,iPhone 还是 iPhone。
iNVERT cASE 翻转每个字母大小写,Hello 变 hELLO;ranDOm CasE 每次结果都不一样,没法复现。清洗数据我基本不用这两个。
只有 iNVERT cASE 和 ranDOm CasE 没有默认快捷键,其余六条都有。官方手册的“转换大小写为”一节没记录任何快捷键,上面这几个是我机器上和社区快捷键表里一致的绑定;按了没反应就去“设置 → 快捷键映射器”看实际绑定。
空白操作默认作用于整个文档,v8.4.9 起才支持选区
手册里的一条总注,也是容易出事的地方:
- 默认情况下所有“空白字符操作”命令作用于整个文档,不管有没有选区
- v8.4.9 起,如果有一个普通流式选区,操作只作用于选中文本
- 多个选区(多光标)时,只有最后添加的“主选区”受影响
- 列选区时不执行任何 trim 或 Tab 转换
最后一条最坑:你以为选中一列跑 trim,结果要么什么都没发生,要么它作用于全文了。想给某一列做 trim,没有内置办法,只能先把那列复制出来单独处理。
判断版本看“? → 关于”。低于 v8.4.9 的话所有 trim 都是全文操作,动手前一定先另存。
七、实战:三条完整流水线
三个案例都用 Notepad++ 跑过,数据脱敏过。步骤按真实操作顺序写。
案例 1:大日志 → 几十行错误摘要
输入:12 万行 Java 日志,混着 INFO、WARN、ERROR,行长 150 到 400 字符。目标:拉出所有 ERROR,去重,看一共几种错误。
2026-08-14 09:12:03.441 [http-nio-8080-exec-7] INFO c.e.order.service.OrderService - order created id=20260814000123
2026-08-14 09:12:03.902 [http-nio-8080-exec-7] ERROR c.e.order.service.PayService - pay timeout orderId=20260814000123 channel=WEIXIN
2026-08-14 09:12:04.117 [http-nio-8080-exec-9] WARN c.e.order.service.StockService - stock low sku=SKU-88213 remain=3
2026-08-14 09:12:05.003 [http-nio-8080-exec-7] ERROR c.e.order.service.PayService - pay timeout orderId=20260814000125 channel=WEIXIN
第一步:看行尾符。 状态栏显示 Unix (LF),全文统一,跳过。
第二步:只留 ERROR 行。 Ctrl+F → 标记 → 填 ERROR → 勾“书签行” → 标记全部。状态栏显示标记了 3,842 行。
第三步:提取到新标签。 “搜索 → 书签 → 复制书签行”→ Ctrl+N → Ctrl+V,存成 errors.txt。原文件关掉不动。
第四步:抹掉时间戳和线程名,否则每行都不一样,去重没意义:
^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ \[[^\]]+\] ERROR
替换串留空。剩下 c.e.order.service.PayService - pay timeout orderId=20260814000123 channel=WEIXIN。
第五步:把订单号也抹掉,不然每个订单一条还是去重不掉:orderId=\d+ 替换成 orderId=X。channel=\w+ 同理,看你要不要保留渠道信息。
第六步:去重。 “编辑 → 行操作 → 删除重复行”。3,842 行变 27 行。
这个案例的精髓在第四、五步。 日志天然每行唯一(有时间戳),直接去重一行都删不掉,必须先“归一化”把不该参与比较的字段抹平。这步想不明白,去重命令点一百次也没用。
案例 2:Excel 导出 CSV → 干净名单
输入:3,600 行 CSV,三个来源合并,重复严重,行尾带空格,中间夹空行。
序号,姓名,手机号,城市,来源
1,张伟,13800138001,杭州,线下活动
2,李娜,13800138002,北京,官网注册
3,王强,13800138001,上海,线下活动
4,张伟,13800138001,杭州,线下活动
第一步:另存。 Ctrl+Alt+S 存成 contacts_raw.csv。
第二步:清空白。 “编辑 → 空白字符操作 → 移除首尾空格”,干掉最后一行 线下活动 末尾那个空格。
第三步:去空行。 “编辑 → 行操作 → 移除空行(含空白字符行)”。
第四步:按手机号去重。 走第三章路 3。手机号是第 3 列且都是 11 位等宽,Alt 拖列选区能对齐,省掉补空格那一步:
Alt+Shift+↓拉出零宽列选区 →Alt+C插 1 到 3600,4 位前导零Alt拖选手机号那一列 → “升序排序行”,稳定排序让同号码组内保持原顺序- 正则删组内多余行:
^(.{4}[^,]*,[^,]*,)([^,]*)(,.*)(\R.{4}[^,]*,\2,.*)+$→\1\2\3 - “升序排序行”按行号排回,列编辑删掉行号
结果:3,600 行 → 2,914 行。表头如果在合并时重复过,第四步顺手就去了。
踩过的坑:第一次做这份数据我跳过了第二步,只删掉 200 多行;补上“移除首尾空格”之后删到 600 多行。行尾一个空格,能让去重能力打三折。
案例 3:几千行配置 → 提取 IP 并排序去重
输入:4,800 行 Nginx 配置,IP 散落在十几个 upstream 块和 allow 规则里。目标:拉出所有后端 IP,去重,按 IP 数值排序。
upstream api_order {
server 10.20.31.11:8080 weight=5;
server 10.20.31.12:8080 weight=5;
server 10.20.31.11:8080 backup;
}
location /api/ {
allow 10.20.40.5;
allow 192.168.100.200;
deny all;
}
第一步:挑出含 IP 的行。 Ctrl+F → 标记 → 勾“正则表达式” → 填 \b\d{1,3}(\.\d{1,3}){3}\b → 勾“书签行” → 标记全部。
第二步:复制到新标签。 “搜索 → 书签 → 复制书签行”→ Ctrl+N → Ctrl+V,得到约 180 行。
第三步:删掉 IP 之外的部分。
^.*?(\d{1,3}(?:\.\d{1,3}){3}).*$
替换串 \1。.*? 是懒惰匹配,保证抓每行第一个 IP。
第四步:去重。 “编辑 → 行操作 → 删除重复行”。180 行 → 43 行。
第五步:按 IP 数值排序。 必须用“按整数升序排序”,不能用默认的按字符编码。手册里明确写了按整数排序会把 IP 排得比较合理。用默认排序时 10.x 和 192.x 的结果看着像对的,纯属巧合,换成 10.x 和 9.x 就露馅了。
结果:43 个唯一 IP,按数值排好,直接贴进巡检表。价值在第三步和第五步的组合:提取(正则)+ 去重(内置)+ 排序(选对变体)。
八、TextFX 已经不能用了
从七八年前的教程过来的话,大概率见过推荐装 TextFX 做排序、去重、大小写转换的内容。现在不用找了。
发生了什么
第一层:从来就没有 64 位版。 TextFX 最后一个官方版本是 0.2.6,发布于 2009 年,那一年还没有 64 位版 Notepad++(64 位是 v7.0 才有)。所以它从来没在 64 位上被官方支持过。
第二层:v8.4.3 起被主动禁用。 这一层很多人不知道。2022 年 7 月的 v8.4.3 之后,Notepad++ 会主动禁用机器上残留的旧版 TextFX,插件从菜单里消失,插件列表也搜不到。
官方理由是:这个插件的某些操作会让 Notepad++ 崩溃,而编辑器崩溃对数据完整性有风险。原话大意是“插件动作导致崩溃,这对数据完整性很危险”。
技术根因是 Scintilla 5.1.5 改了一个 API 的返回值语义:SCI_GETCURLINE、SCI_GETTEXT 这类消息不再返回末尾多出的那 1 字节。Notepad++ v8.4 跟着升到 Scintilla 5.x,TextFX 里所有依赖旧行为的代码路径就全错位了,而它停更十几年,没人修。
所以这不是“兼容性警告”,是“装上会把文件搞坏,所以不让你装”。残留的旧文件留着不碍事(不会被加载),降级回 v8.4.2 能复活,但意味着永远不升级。
功能替代对照表
官方社区的 TextFX 功能替代清单有一份完整对照,我按“用什么替代”整理,并加了一列我的建议:
| TextFX 原功能 | 现在怎么做 | 我的建议 |
|---|---|---|
| 排序行 | “编辑 → 行操作”9 种变体 | 内置,比 TextFX 强 |
| 删除重复行 | “编辑 → 行操作 → 删除重复行” | 内置全局去重,TextFX 当年做不到 |
| 大小写转换 | “编辑 → 转换大小写为”8 种 | 内置,还有 blend 版本 |
| 移除空行 / 尾随空格 | “编辑 → 行操作”“编辑 → 空白字符操作” | 内置 |
| 引号转换 | 正则替换,或录宏 | 一次性用正则,常做就录宏 |
| 行操作组合动作 | 录一个宏把几步串起来 | 宏最划算 |
| 复杂条件行处理 | PythonScript 写脚本 | 重复超过三次就写脚本 |
| 就是想要 TextFX 界面 | NPPTextFX2(第三方移植) | 见下面 |
NPPTextFX2:GitHub 上的第三方移植版,作者在 README 里说 64 位版本功能已完整(2026 年 2 月更新过)。我没在 64 位上逐条试,以你实际装到的版本为准。
我的看法:先查这张表,八成已被内置覆盖。真找不到替代再考虑 NPPTextFX2,别把它放进每周都要跑的流程里。
九、什么时候该换工具
Notepad++ 处理文本有明确舒适区,出了这个区,硬撑的时间成本会超过学个新工具。
行数阈值。 我的经验值:几万行以内上面所有操作都还流畅。十万行往上,删除重复行 和排序明显卡顿,正则里 (\R...)+ 这类有回溯的模式可能跑几十秒甚至假死。超过 50 万行我会先切文件或者换工具。这阈值跟机器配置关系很大,当参考别当标准。
需要分组聚合时。 “按城市统计每个城市多少条”这类活在 Notepad++ 里做是自己找罪受,不如一行 SQL:
SELECT city, COUNT(*) FROM contacts GROUP BY city ORDER BY COUNT(*) DESC;
数据能进 SQLite 就进 SQLite,一行 GROUP BY 顶你半小时。
需要真正的 diff 合并时。 Compare 插件能对照差异,但我的体验是它没有一个顺手的“把所有差异一次性导出”的用法,得手动一条条跳。真要做合并评审,用 VS Code 的对比或者 Beyond Compare 更省事。
需要保留处理历史时。 清洗流水线跑完,你很难说清这文件经过了哪几步。要交付给别人、或者下周还要重跑的活,写成脚本比记一串菜单点击可靠得多。
一句话判断:一个操作要重复三次以上,就值得写成脚本或宏。
下一步
这篇文章覆盖“编辑 → 行操作”“编辑 → 空白字符操作”“搜索 → 书签”这条线。往回补基础看Notepad++ 入门教程(界面、列编辑、多光标、快捷键),往前走看正则替换 15 个实例和行尾符与 CRLF/LF 转换。
三个常被问到的问题:
删除重复行能保留最后一次出现的那行吗? 内置命令不行,它只保留第一次出现的。要保留最后一次,先“编辑 → 行操作 → 倒序排列”把文件翻转,跑完去重再倒序翻回来。倒序之后“第一次出现”就变成了原来的“最后一次”。
点了删除重复行,行数一个没变,是命令坏了吗? 大概率不是。按第三章末尾的四查清单走一遍:大小写、尾随空格、行尾符混用、全角半角。九成是尾随空格。
能只排序文件的一部分吗? 能。选中那几行再点排序命令,只有选区跨到的行参与排序。注意选区末端别多带一行,见第二章末尾。
还有没解决的问题去常见问题看看。