先把行數差額算清楚
把一份備份日誌整貼進輸入框,每行一個路徑,點提取,輸出比輸入少了幾行——先別急著懷疑工具漏行。我拿 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。機制三點:結尾分隔符的回退只兜一格,出去的空串連統計都不進;「取消包含擴展名」按最後一個點下刀且不冪等;去重逐字比對、大小寫敏感。清單不同數會變,對賬還是這兩個減法。