先把行数差额算清楚
把一份备份日志整贴进输入框,每行一个路径,点提取,输出比输入少了几行——先别急着怀疑工具漏行。我拿 20 行夹具对账,统计条显示 总路径数:17、提取文件名:16、唯一文件名:14:3 行空白在计数前就被跳过,连 17 都没进;那行单独的斜杠进了 17,却在输出里被无声丢掉,停在 16。输出与输入不再按行号对应,界面不会说是哪一行。
结尾分隔符的回退:只兜一格
D:\a\ 切分得 3 段,末段空,回退一格拿倒数第二段,交出 a;/var/www/ 与 a/ 同理。但回退没有循环:末尾连写两个分隔符的 D:\a\\ 末段与次末段全空,返回空串;a//、单独一行的 / 与 \ 同样。中段连续反而无害,取末段不看空段,a//b.txt 照出 b.txt。
图 1|兜一格与兜不住的区别,全在同一函数里逐字实测。
两种分隔符的入门判断见上一篇从路径里批量提取文件名;这里只量不报错的位置。
统计条三个数与开关四组合
行数账:20 行里 3 行 trim 后为空、不进 total,1 行抽出空名被丢,16 减 14 等于 2——report.pdf 与 photo.JPG 各重复两次。字节账:
| 开关组合 | 统计条(总数/提取/唯一) | 输出 |
|---|---|---|
| 扩展名勾上、不去重 | 17 / 16 / 14 | 16 行,165 字节 |
| 扩展名勾上、去重勾上 | 17 / 14 / 14 | 14 行,144 字节 |
| 扩展名取消、不去重 | 17 / 16 / 14 | 16 行,102 字节 |
| 扩展名取消、去重也勾上 | 17 / 14 / 14 | 14 行,89 字节 |
输出只用 LF 拼接、结尾不带换行。CRLF 与 LF 两版夹具的统计三数与输出字符数完全一致(17、16、165),差的只是输入字节(374 对 355);结尾多粘一个换行把切分从 20 段推到 21 段,统计条纹丝不动。
图 2|同一夹具四种开关的输出字节(条长按每字节 2 单位)。
查询串与片段:整块留在名字里
一条 50 字符的 CDN 地址,勾选扩展名输出 22 字符的 a.jpg?w=800&h=600#frag:本页拿行只按分隔符切段,?query#frag 就是名字的一部分,不解析 URL,也不还原百分号编码。
取消扩展名后画风突变。这 22 字符里只剩「a.jpg」前那一个点,位于 index 1,一刀削掉 21 个字符,94.5% 蒸发,只剩 1 个字符的 a。点更多的有曲折:/files/report.csv?v=1.2 取消扩展名得 14 字符的 report.csv?v=1,最后一个点落在查询值 1.2 的小数点上,削剩的串带着 ?v=,既不是文件名也不是干净的扩展名切分;/download/report.pdf?v=2 反而干净,输出 report。URL 和 Windows 路径走的是同一把刀。
点号刀法:规则两条,变形全从规则来
「取消包含扩展名」的实现只有两句:在末段找最后一个点,位置严格大于 0 才下刀。逐条实测:
- 多段扩展名只削最后一段:a.tar.gz 变 a.tar(5 字符)、archive.tar.bz2 变 archive.tar(11 字符)、a.b.c.d 变 a.b.c;
- 点在第 0 位不动刀:.gitignore 原样保留;.hidden.txt 末点照切只剩 .hidden;
- 末尾点被当成扩展名:name. 变 name,连目录点 .. 都被削成一个 .;
- 无点整串不动:README 仍是 README。
这一刀还不幂等:把 16 行输出粘回去跑第二遍,a.tar 继续变 a、archive.tar 继续变 archive,2 项变形;勾选扩展名那档二遍变化项 0、行数仍是 16。所以别把「取消包含扩展名」当成「去掉扩展名」,多跑一遍就多削一层。
去重:逐字比,大小写也算不同
去重按输出名精确匹配、含大小写:/a/photo.JPG、/b/photo.jpg、/c/PHOTO.JPG 勾上去重仍输出 3 行,统计显示 唯一文件名:3。夹具 16 到 14 靠 report.pdf 与 photo.JPG 各重复两次,photo.JPG 两行里一行带首尾空白,trim 后才并得起来。
盘符与 URL 根:交出的是另一种串
混进批量的非文件路径行都有固定结果:盘符根 C:\ 返回 2 字符的 C:,串里没点,取消扩展名也不动;URL 根的「文件名」其实是主机名,https://example.com/ 出 11 字符的 example.com,取消后剩 7 字符;没有斜杠的协议串整条当名字,mailto:support@example.com 原样 26 字符,取消扩展名削掉尾巴 .com 后剩 22 字符。函数不知道盘符、主机名、邮箱是什么,只会切段和找点。
200 行是一份 0.154 ms 的账
把同一份夹具复制 10 遍成 200 行 CRLF 输入、3758 字节,在批量提取文件名这个动作上实测一次 0.154 ms,输出 160 行,唯一文件名仍是 14;勾去重反而更快,0.1223 ms、14 行。行数账线性放大:总路径数 170、提取文件名 160。页面没有长度校验、没有截断。
几处容易看走眼的地方
Q:去重会把 photo.JPG 和 photo.jpg 并成一条吗?
不会,精确匹配且大小写敏感,三条全留,唯一文件名:3。
Q:示例按钮的内容能当基准吗?
能:示例 6 行输入 155 字符 / 163 字节、LF 分隔且结尾无换行,第 4 行是第 1 行的刻意重复;跑完输出 6 行、统计条 6 / 6 / 5,可作干净基准。
把这几格账带回去
这份夹具里 17、16、14、20 互相咬合:20 行进、3 行空白不计、1 行空名被吞、16 行出、两处重复并成 14。机制三点:结尾分隔符的回退只兜一格,出去的空串连统计都不进;「取消包含扩展名」按最后一个点下刀且不幂等;去重逐字比对、大小写敏感。清单不同数会变,对账还是这两个减法。