數(shù)字規(guī)則漏了一半)
版權(quán)與內(nèi)容來(lái)源聲明本文為原創(chuàng)整理。文中涉及官方文檔、開(kāi)源倉(cāng)庫(kù)、論文與公開(kāi)報(bào)道的內(nèi)容均在附表 A 中標(biāo)注來(lái)源引用官方原文保持原樣不作改寫。文中命令、版本號(hào)與界面截圖以本文成文時(shí)的實(shí)測(cè)/核驗(yàn)結(jié)果為準(zhǔn)標(biāo)注「待驗(yàn)證」的部分請(qǐng)以你本地環(huán)境實(shí)際輸出為判斷依據(jù)。本文不推薦任何不合規(guī)的軟件獲取方式也不對(duì)任何收益結(jié)果作承諾。轉(zhuǎn)載請(qǐng)注明出處。一、為什么這條線容易漏脫敏指的是在日志落盤、導(dǎo)出或外發(fā)之前把手機(jī)號(hào)、身份證號(hào)、銀行卡號(hào)這類字段替換成星號(hào)或占位符的動(dòng)作。絕大多數(shù)團(tuán)隊(duì)做這件事的方式是一樣的寫一條正則把「看起來(lái)像手機(jī)號(hào)」的數(shù)字換掉收工。問(wèn)題不在于大家不會(huì)寫正則。正則指的是用一串符號(hào)描述「什么樣的字符串算命中」的規(guī)則文本會(huì)寫re.sub的人很多。問(wèn)題在于這條規(guī)則從來(lái)沒(méi)有被證偽過(guò)——它上線之后只跑正常樣本或者只在「格式整齊」的樣本上跑漏了也沒(méi)人知道因?yàn)槊撁袈┝瞬粫?huì)報(bào)錯(cuò)。1.1 第一版腳本幾乎都長(zhǎng)這樣下面三行是從主代理的本機(jī)實(shí)測(cè)腳本里原樣摘出來(lái)的屬于已經(jīng)跑過(guò)的寫法不是示意importre# 摘自 work/2026-10-22_脫敏實(shí)測(cè).py這三條是實(shí)跑過(guò)的R1re.compile(r1[3-9]\d{9})# 只認(rèn)連續(xù) 11 位R2re.compile(r1[3-9]\d[- ]?\d{4}[- ]?\d{4})# 允許半角空格與短橫R3re.compile(r(?:\?86)?1[3-9]\d{9})# 允許 86 前綴1[3-9]的意思是「第一位是 1、第二位是 3 到 9」后面跟九個(gè)數(shù)字。這條規(guī)則在紙面上沒(méi)錯(cuò)中國(guó)內(nèi)地手機(jī)號(hào)的號(hào)段確實(shí)落在這個(gè)范圍里。但它描述的是號(hào)碼本身不是號(hào)碼在日志里的樣子。1.2 漏的不是規(guī)則是寫法分支同一批手機(jī)號(hào)在真實(shí)日志里至少有四種寫法。我按這四種寫法各構(gòu)造了 5 條樣本一共 15 條逐個(gè)喂給上面三條規(guī)則。寫法各 5 條日志里的樣子用哪條規(guī)則原樣先歸一化連續(xù) 11 位用戶 13812345678 提交訂單R15/55/5帶半角分隔手機(jī) 159 0000 1111 待確認(rèn)R10/50/5帶半角分隔聯(lián)系 135 1111 2222R25/55/5全角或帶前綴手機(jī)R14/55/5這張表里有一行特別值得看「全角或帶前綴」這一類R1 原樣就能抓到 4/5。原因是這 5 條里只有 1 條真的用了全角數(shù)字另外 4 條是半角數(shù)字配中文標(biāo)點(diǎn)、括號(hào)、86或0086前綴R1 在字符串中間照樣能找到那 11 位。所以「原樣 4/5」這個(gè)數(shù)字會(huì)給人一個(gè)虛假的安心感——看起來(lái)只差一點(diǎn)點(diǎn)實(shí)際上差的是整整一個(gè)寫法類別。而「半角分隔」那一行是 0/5怎么調(diào)前綴、怎么加86都還是 0/5因?yàn)橹虚g的空格和短橫不在規(guī)則的胃口里。規(guī)則寫得多花和覆蓋了哪些寫法是兩件不相關(guān)的事。判據(jù)一召回先看寫法覆蓋不看正則寫得多花。動(dòng)手寫規(guī)則之前先把「這套日志里出現(xiàn)過(guò)幾種寫法」列成清單四種寫法就是四行樣本一行都不能省。1.3 本文的樣本與口徑必須先把口徑說(shuō)清楚樣本是構(gòu)造樣本非真實(shí)業(yè)務(wù)日志僅用于對(duì)比規(guī)則寫法。6 類敏感字段各 5 條手機(jī)號(hào)連續(xù) 11 位、手機(jī)號(hào)帶半角分隔符、手機(jī)號(hào)全角或帶前綴、身份證 18 位、銀行卡 16–19 位、郵箱另有 6 條不該被動(dòng)的正常字段訂單號(hào)、13 位毫秒時(shí)間戳、運(yùn)單號(hào)、12 位批次號(hào)、13 位商品條碼、15 位流水號(hào)。跑測(cè)環(huán)境是 Python 3.13.14僅用標(biāo)準(zhǔn)庫(kù)re腳本與日志都在work/目錄下任何人可以復(fù)跑。所以下面所有分母都是 5所有數(shù)字都能回到日志里逐行對(duì)上。二、六類字段的寫法覆蓋實(shí)測(cè)先把完整的對(duì)照表放出來(lái)。每一格是「原樣匹配 → 先做全角轉(zhuǎn)半角再匹配」分母都是 5。規(guī)則手機(jī)號(hào)·連續(xù) 11 位手機(jī)號(hào)·帶分隔符手機(jī)號(hào)·全角或帶前綴身份證·18 位銀行卡·16~19 位郵箱R1 連續(xù) 11 位5/5 → 5/50/5 → 0/54/5 → 5/55/5 → 5/50/5 → 0/50/5 → 0/5R2 允許半角分隔5/5 → 5/55/5 → 5/54/5 → 5/55/5 → 5/50/5 → 0/50/5 → 0/5R3 帶 86 前綴5/5 → 5/50/5 → 0/54/5 → 5/55/5 → 5/50/5 → 0/50/5 → 0/5R4 身份證 18 位0/5 → 0/50/5 → 0/50/5 → 0/55/5 → 5/52/5 → 2/50/5 → 0/5R5 銀行卡 16~19 位0/5 → 0/50/5 → 0/50/5 → 0/55/5 → 5/53/5 → 3/50/5 → 0/5R6 郵箱0/5 → 0/50/5 → 0/50/5 → 0/50/5 → 0/50/5 → 0/55/5 → 5/52.1 手機(jī)號(hào)兩個(gè)召回臺(tái)階分別歸功于不同的動(dòng)作召回指的是「該抓到的里面實(shí)際抓到了多少」。把三類手機(jī)號(hào)寫法合起來(lái)算 15 條R1 樸素規(guī)則原樣9/1560.0%先歸一化10/1566.7%。R2 允許半角分隔原樣14/1593.3%先歸一化15/15全部命中。兩個(gè)臺(tái)階要分開(kāi)看。從 9 漲到 10 是歸一化帶來(lái)的漲的只有全角那 1 條從 10 漲到 15 是寫法覆蓋帶來(lái)的靠的是規(guī)則里多認(rèn)了[- ]?這兩處分隔符。很多人只做了前者寫了個(gè)translate或者只做了后者把規(guī)則寫長(zhǎng)所以永遠(yuǎn)停在 10/15 或 14/15。標(biāo)題里說(shuō)的「漏了一半」指的就是 9/15 這個(gè)起點(diǎn)15 條樣本樸素規(guī)則原樣只認(rèn)了 9 條剩下 6 條一條都不會(huì)報(bào)錯(cuò)、一條都不會(huì)告警。2.2 身份證與銀行卡位數(shù)不是判據(jù)這張表里最別扭的兩行是 R4 和 R5。R4 是\d{17}[\dXx]在 5 條身份證樣本上5/5。這里有一個(gè)必須寫死的細(xì)節(jié)樣本里有一條的末位是小寫x只寫大寫X會(huì)漏掉它必須寫[Xx]。漏掉的結(jié)果不是報(bào)錯(cuò)是那一條身份證原樣落進(jìn)了日志。R5 是\d{16,19}在 5 條銀行卡樣本上只命中3/56222 0212 3456 7890帶空格、6217-0000-1111-2222帶短橫的兩條全部漏掉。同時(shí)它把 5 條 18 位身份證全部吃了進(jìn)來(lái)5/5——因?yàn)?18 位純數(shù)字正好落在 16 到 19 位這個(gè)區(qū)間里。反過(guò)來(lái)的方向也一樣R4身份證規(guī)則在銀行卡那一列命中了 2/5說(shuō)明這兩條規(guī)則在互相吃?!付嗌傥粩?shù)字」只能篩出一個(gè)候選集合不能判定字段類型。這是本文后面所有錨點(diǎn)討論的起點(diǎn)。2.3 郵箱這一條反而最穩(wěn)郵箱規(guī)則[\w.-][\w-]\.[\w.]在 5 條樣本上5/5本輪沒(méi)有參與任何一次誤判。原因不神秘它中間有一個(gè)。是一個(gè)幾乎不會(huì)出現(xiàn)在訂單號(hào)、時(shí)間戳、運(yùn)單號(hào)里的字符等于規(guī)則自帶了一個(gè)錨點(diǎn)。這個(gè)對(duì)比很值錢——凡是自帶稀有分隔符的字段規(guī)則都容易寫對(duì)凡是「純數(shù)字」的字段規(guī)則都容易寫歪因?yàn)榧償?shù)字的世界里沒(méi)有任何天然邊界。三、誤判清單什么被當(dāng)成了手機(jī)號(hào)誤判指的是不該動(dòng)的字段被動(dòng)了。6 條正常字段、6 條規(guī)則交叉跑下來(lái)一共產(chǎn)生11 次誤判。正常字段值被哪條規(guī)則誤判為什么會(huì)被吃13 位毫秒時(shí)間戳1759999999999R1 / R2 / R313 位里含一段以 1 開(kāi)頭、第二位是 7 的 11 位運(yùn)單號(hào)SF1381234567890R1 / R2 / R3字母后面那 13 位里含同樣形狀的 11 位15 位流水號(hào)159000011112222R1 / R2 / R315 位里含一段 1 開(kāi)頭、第二位是 5 的 11 位18 位訂單號(hào)202610221234567890R4 / R518 位純數(shù)字正好滿足「17 位 1 位」與「16 到 19 位」12 位批次號(hào)202610220001無(wú)位數(shù)不夠 16也沒(méi)有 11 位以 1[3-9] 開(kāi)頭的連續(xù)段13 位商品條碼6901234567892無(wú)位數(shù)不夠 16首位是 6 不是 13.1 13 位時(shí)間戳是重災(zāi)區(qū)1759999999999這條同時(shí)被三條手機(jī)號(hào)規(guī)則命中是這輪實(shí)測(cè)里最典型的失敗。它是 13 位毫秒時(shí)間戳——日志里最常見(jiàn)的字段之一幾乎每一行都有。為什么 11 位規(guī)則能吃 13 位因?yàn)檎齽t默認(rèn)是子串搜索不是整串匹配。1[3-9]\d{9}只要求「存在這么一段」不要求「這段前后沒(méi)有別的數(shù)字」。時(shí)間戳的第 1 位是 1、第 2 位是 7剛好滿足1[3-9]后面再湊 9 個(gè)數(shù)字就命中了。規(guī)則本身完全沒(méi)錯(cuò)錯(cuò)在它沒(méi)有說(shuō)「前后不許再挨著數(shù)字」。3.2 訂單號(hào)同時(shí)命中兩條長(zhǎng)規(guī)則202610221234567890是 8 位日期加 10 位序列共 18 位。它同時(shí)滿足 R417 位 1 位和 R516 到 19 位也就是說(shuō)身份證規(guī)則和銀行卡規(guī)則都會(huì)把它打成星號(hào)。這比手機(jī)號(hào)誤判更麻煩訂單號(hào)是排障時(shí)最主要的檢索鍵。把訂單號(hào)脫掉線上出問(wèn)題時(shí)按訂單號(hào)搜日志會(huì)直接搜不到人只能按時(shí)間盲翻。3.3 誤刪比漏刪更難發(fā)現(xiàn)漏刪是「該掩的沒(méi)掩」誤刪是「不該掩的掩了」。這兩件事在監(jiān)控上的可見(jiàn)度完全不對(duì)稱漏刪日志內(nèi)容看起來(lái)正常沒(méi)有任何異常信號(hào)只有等審計(jì)或等出事才知道。誤刪日志內(nèi)容變短、字段變成星號(hào)但沒(méi)有人會(huì)為「日志里少了一個(gè)訂單號(hào)」告警。判據(jù)四誤刪比漏刪更該被盯住。漏刪沒(méi)有任何信號(hào)誤刪卻會(huì)悄悄讓日志失去排障能力而后者通常沒(méi)人報(bào)警。所以判斷一條規(guī)則好不好不能只看它抓到了多少敏感字段還要看它在正常字段上留了幾個(gè)洞。本案的 11 次誤判分布在 4 個(gè)正常字段上其中 3 個(gè)是排障必用的定位鍵時(shí)間戳、運(yùn)單號(hào)、訂單號(hào)。四、歸一化與錨點(diǎn)兩個(gè)必做的動(dòng)作4.1 歸一化必須在匹配之前歸一化指的是在比對(duì)之前先把不同寫法統(tǒng)一成一種形式——這里具體指全角數(shù)字轉(zhuǎn)半角數(shù)字。# 摘自 work/2026-10-22_脫敏實(shí)測(cè).py這兩行是實(shí)跑過(guò)的FWstr.maketrans(,0123456789)texts.translate(FW)# 先歸一化再拿 text 去匹配這一步的收益在數(shù)字上很小R1 從 9/15 到 10/15R2 從 14/15 到 15/15都只多了 1 條。但它補(bǔ)的是整整一個(gè)類別而且這一類是「規(guī)則怎么寫都補(bǔ)不上」的。有個(gè)常見(jiàn)的誤解值得點(diǎn)出來(lái)有人覺(jué)得\d本來(lái)就能匹配全角數(shù)字所以不用歸一化。按 Python 官方文檔re模塊的說(shuō)明\d在 Unicodestr模式下確實(shí)匹配任何 Unicode 十進(jìn)制數(shù)字包括全角數(shù)字。但問(wèn)題出在規(guī)則的另一半——1[3-9]里的1和3-9都是 ASCII 字面量…這一行在第一個(gè)字符就斷了根本走不到后面的\d。所以把[3-9]換成\d救不了全角只有把文本先歸一化才行。順序也不能反判據(jù)二歸一化必須放在匹配之前。先匹配、后歸一化等于用錯(cuò)誤的輸入做了一次判斷再補(bǔ)救已經(jīng)晚了。4.2 錨點(diǎn)給長(zhǎng)數(shù)字規(guī)則加前后邊界錨點(diǎn)指的是在規(guī)則兩頭加上「前面必須是什么、后面必須是什么」的約束。對(duì)純數(shù)字字段來(lái)說(shuō)最有用的一種錨點(diǎn)是否定型數(shù)字邊界前后不許緊挨著數(shù)字或分隔符。??代碼待驗(yàn)證# 本文改進(jìn)寫法未在主代理的實(shí)測(cè)腳本里跑過(guò)PHONEre.compile(r(?![\d\-])# 前面不能是數(shù)字或短橫r(?:(?:\|00)?86[\- ]?)?# 可選國(guó)家碼86 / 0086r1[3-9]\d(?:[\- ]?\d{4}){2}# 3 位號(hào)段 兩組 4 位r(?![\d\-])# 后面不能是數(shù)字或短橫)按這個(gè)結(jié)構(gòu)前面那 11 次誤判里能被推掉的是三類13 位時(shí)間戳、15 位流水號(hào)、13 位運(yùn)單號(hào)里的數(shù)字部分。機(jī)制是(?![\d\-])——時(shí)間戳那 11 位后面還跟著99邊界斷言不成立整條匹配失敗正則不會(huì)退而求其次去匹配一個(gè)短一點(diǎn)的子串。但18 位訂單號(hào)推不掉。它本身就是 18 位純數(shù)字前后都沒(méi)有別的數(shù)字任何「前后不挨數(shù)字」的斷言對(duì)它都是成立的。要區(qū)分它和身份證只能看它前面寫的是「訂單號(hào)」還是「身份證」——這就是下一節(jié)。另外提醒一個(gè)反向的坑加了(?![\d\-])之后008613812345678這種緊貼國(guó)家碼的寫法會(huì)被前面那個(gè)0擋住所以國(guó)家碼部分要顯式允許00前綴否則會(huì)新造一個(gè)漏點(diǎn)。這類「修一個(gè)漏點(diǎn)、長(zhǎng)出另一個(gè)漏點(diǎn)」的情況只有靠用例回歸才攔得住。4.3 位數(shù)不夠必須看字段名前綴判據(jù)三長(zhǎng)數(shù)字規(guī)則必須帶上下文錨點(diǎn)。把上面的結(jié)論壓成一句位數(shù)只能篩候選字段名才能定類型。同一個(gè) 18 位數(shù)字串出現(xiàn)在「訂單號(hào) 202610221234567890」里是業(yè)務(wù)主鍵出現(xiàn)在「身份證 110101199003071234」里是敏感個(gè)人信息。正則看到的兩個(gè)串長(zhǎng)得一模一樣它沒(méi)有辦法自己判斷。能判斷的信息在字段名前綴上——也就是那個(gè) 18 位數(shù)字前面若干個(gè)字符里出現(xiàn)的「身份證」「證件號(hào)」「卡號(hào)」「賬號(hào)」這類詞。工程上的做法是關(guān)鍵詞窗口不是全行搜索而是要求敏感詞出現(xiàn)在匹配位置之前的一個(gè)有限窗口內(nèi)比如前 8 個(gè)字符。窗口不能開(kāi)太大否則一行里同時(shí)有「身份證」和「訂單號(hào)」時(shí)又會(huì)串味窗口也不能不開(kāi)否則就等于回到純位數(shù)判斷。這里要接受一個(gè)事實(shí)關(guān)鍵詞窗口是業(yè)務(wù)知識(shí)不是正則技巧。它依賴你對(duì)自家日志格式的了解換一個(gè)系統(tǒng)就得重寫。這也是為什么脫敏規(guī)則沒(méi)法直接從網(wǎng)上抄一份通用的。五、上線前的五個(gè)自檢用例自檢用例的價(jià)值不在于「證明規(guī)則能跑」而在于能證偽。一條用例如果怎么改規(guī)則都能過(guò)它就沒(méi)有存在意義。判據(jù)五規(guī)則要能被證偽。下面五個(gè)用例是從上面 11 次誤判里反推出來(lái)的每個(gè)都對(duì)準(zhǔn)一種具體的失敗模式。用例輸入片段構(gòu)造樣本期望結(jié)果對(duì)準(zhǔn)的失敗模式同行混排用戶 13812345678 下單 ts1759999999999手機(jī)號(hào)被掩時(shí)間戳原樣子串誤吃長(zhǎng)數(shù)字寫法混排聯(lián)系 159 0000 1111備用兩條都被掩分隔符與全角各漏一類末位小寫證件號(hào) 11010119900307123x被掩[Xx]只寫了大寫長(zhǎng)數(shù)字互吃訂單號(hào) 202610221234567890 卡號(hào) 6222021234567890訂單號(hào)原樣卡號(hào)被掩兩位數(shù)規(guī)則互相吃單號(hào)帶字母郵箱 zhangsanexample.com 運(yùn)單號(hào) SF1381234567890郵箱被掩運(yùn)單號(hào)原樣字母前綴沒(méi)進(jìn)錨點(diǎn)??代碼待驗(yàn)證# 用例斷言輸出里必須出現(xiàn) expected 里的每個(gè)片段順序不限CASES[(同行混排,用戶 13812345678 下單 ts1759999999999,[138****5678,1759999999999]),(寫法混排,聯(lián)系 159 0000 1111備用,[159****1111,138****5678]),(末位小寫,證件號(hào) 11010119900307123x,[110101********123x]),(長(zhǎng)數(shù)字互吃,訂單號(hào) 202610221234567890 卡號(hào) 6222021234567890,[202610221234567890,6222********7890]),(單號(hào)帶字母,郵箱 zhangsanexample.com 運(yùn)單號(hào) SF1381234567890,[z***example.com,SF1381234567890]),]寫用例時(shí)有個(gè)細(xì)節(jié)容易漏期望值要寫「原樣保留」的那一半。只斷言「敏感字段被掩了」規(guī)則把整行都打成星號(hào)也能通過(guò)把「訂單號(hào)必須原樣出現(xiàn)」寫進(jìn)斷言誤刪才會(huì)變成紅燈。這份資料是什么一份按「先跑通再排查」順序整理的大模型學(xué)習(xí)路線圖里面有一節(jié)專門講工程側(cè)的數(shù)據(jù)處理與合規(guī)動(dòng)作該怎么拆步驟。放在資料包里掃碼即可獲取六、一張可抄的規(guī)則表下面這份清單是本文的結(jié)論匯總?!笇?shí)測(cè)量」一列寫的是主代理腳本在本機(jī)跑出來(lái)的結(jié)果「錨點(diǎn)改進(jìn)」一列是本文加的屬于改進(jìn)寫法沒(méi)有實(shí)跑。字段實(shí)測(cè)量分母 5 或 15錨點(diǎn)改進(jìn)要點(diǎn)手機(jī)號(hào)R2 歸一化后 15/15R2 原樣 14/15數(shù)字邊界 顯式國(guó)家碼 分隔符可選身份證5/5但只寫大寫X會(huì)漏末位小寫[\dXx] 關(guān)鍵詞窗口位數(shù)不足以定類型銀行卡3/5帶空格/短橫全漏反向吃身份證 5/5允許分隔符 關(guān)鍵詞窗口 校驗(yàn)位郵箱5/5本輪無(wú)誤判天然錨點(diǎn)保持簡(jiǎn)單不要過(guò)度加約束時(shí)間戳被三條手機(jī)號(hào)規(guī)則誤吃不靠正則排除走豁免清單訂單號(hào) / 運(yùn)單號(hào)被 R4、R5 與 R1 誤吃只能靠字段名關(guān)鍵詞豁免需業(yè)務(wù)方給字段清單??代碼待驗(yàn)證# 本文改進(jìn)寫法錨點(diǎn) 豁免未在主代理腳本中實(shí)跑需按自家日志格式調(diào)FWstr.maketrans(,0123456789)# 1) 豁免清單已知的正常長(zhǎng)數(shù)字匹配前先掛號(hào)脫敏時(shí)跳過(guò)這些區(qū)間EXEMPTre.compile(r(?!\d)1[6-9]\d{11}(?!\d))# 13 位毫秒時(shí)間戳# 2) 四類字段長(zhǎng)規(guī)則先跑短規(guī)則后跑避免 16~19 位吃掉 18 位身份證ID_CNre.compile(r(?![\dXx])\d{17}[\dXx](?![\dXx]))CARDre.compile(r(?![\d\-])\d{16,19}(?![\d\-]))PHONEre.compile(r(?![\d\-])(?:(?:\|00)?86[\- ]?)?1[3-9]\d(?:[\- ]?\d{4}){2}(?![\d\-]))EMAILre.compile(r[\w.-][\w-]\.[\w.])這份清單里有三處是「必須按你家的日志改」的抄的時(shí)候不要整段復(fù)制豁免清單里的時(shí)間戳位數(shù)、國(guó)家碼的寫法、以及銀行卡前后允許哪些分隔符。我這輪樣本里只有空格和短橫兩種分隔實(shí)際日志里可能還有括號(hào)、點(diǎn)號(hào)、斜杠。6.1 掩碼留多少留可定位的部分掩碼指的是用星號(hào)等字符替換敏感片段。留幾位是有講究的留得太少客服核對(duì)不了留得太多等于沒(méi)脫敏。字段建議保留掩碼后保留的理由手機(jī)號(hào)前 3 后 4138****5678前 3 位看號(hào)段后 4 位供本人核對(duì)身份證前 6 后 4110101********1234前 6 位是地區(qū)碼排障時(shí)常按地區(qū)篩銀行卡后 46222********7890后 4 位是用戶報(bào)卡時(shí)唯一會(huì)說(shuō)的信息郵箱首字母 域名z***example.com域名能定位到企業(yè)客戶訂單號(hào) / 時(shí)間戳全部保留原樣它們是排障主鍵脫了就沒(méi)法查6.2 順序與冪等執(zhí)行順序會(huì)直接影響結(jié)果\d{16,19}會(huì)吃掉 18 位身份證所以身份證規(guī)則必須在銀行卡規(guī)則之前跑或者在銀行卡規(guī)則里排除已經(jīng)被身份證規(guī)則占用的區(qū)間。冪等指的是同一段文本處理兩次結(jié)果和一次一樣。掩碼用*替換數(shù)字之后第二次跑時(shí)那些位置已經(jīng)不是數(shù)字了不會(huì)二次命中所以天然冪等。但如果某天有人把掩碼改成「保留位數(shù)、把數(shù)字換成 0」第二次跑就會(huì)因?yàn)槲粩?shù)沒(méi)變而再掩一次長(zhǎng)度悄悄變短。這種改動(dòng)必須在用例里回歸。七、收尾把脫敏當(dāng)接口契約7.1 契約要寫清三件事《中華人民共和國(guó)個(gè)人信息保護(hù)法》第五十一條第三項(xiàng)要求個(gè)人信息處理者「采取相應(yīng)的加密、去標(biāo)識(shí)化等安全技術(shù)措施」。去標(biāo)識(shí)化指的是讓信息在不借助額外信息的前提下無(wú)法指向特定個(gè)人。脫敏腳本就是這條要求最直接的落地點(diǎn)。但落到工程上脫敏不該被當(dāng)成一個(gè)腳本而該被當(dāng)成一份接口契約。契約至少要寫清三件事輸入寫法清單這套日志里手機(jī)號(hào)有幾種寫法、身份證會(huì)不會(huì)帶小寫 x、卡號(hào)會(huì)不會(huì)分組。這份清單要由寫日志的人確認(rèn)不是脫敏的人猜。輸出掩碼格式每個(gè)字段保留幾位、用什么字符掩。這決定了排障的人還能不能干活?;砻庾侄吻鍐文男╅L(zhǎng)數(shù)字是正常字段絕不能動(dòng)。這份清單是誤判的唯一解藥。7.2 規(guī)則要有版本號(hào)也要有回歸最后一條判據(jù)規(guī)則文件要帶版本號(hào)日志落盤處要記下用的是哪一版。理由是誤判的形態(tài)會(huì)變。今天被誤吃的是 13 位時(shí)間戳明天業(yè)務(wù)加了一個(gè) 19 位的內(nèi)部單號(hào)同樣會(huì)被\d{16,19}吃掉。如果日志里沒(méi)有版本信息出問(wèn)題時(shí)你無(wú)法判斷「這條日志里的訂單號(hào)為什么變成星號(hào)」是新規(guī)則造成的還是三個(gè)月前就有的老問(wèn)題?;貧w的方式很簡(jiǎn)單把第 5 章那五個(gè)用例做成每次改規(guī)則都跑的檢查再加一條「正常字段不得被掩」的斷言。用例不需要多需要的是每次都會(huì)跑。這份資料是什么在線可查的大模型知識(shí)庫(kù)里面有 Agent Skills 與工程化落地的專題目錄適合用來(lái)對(duì)照本文這種「一條規(guī)則怎么變成可回歸的接口」的寫法。放在資料包里掃碼即可獲取附表 A本文引用事實(shí)與出處對(duì)照表事實(shí)出處本文位置全部命中與誤判數(shù)字9/15、10/15、14/15、15/15、11 次誤判、5/5、3/5本機(jī)實(shí)測(cè)work/2026-10-22_脫敏實(shí)測(cè).py日志work/2026-10-22_脫敏實(shí)測(cè).logPython 3.13.14僅標(biāo)準(zhǔn)庫(kù) re第 2、3 章手機(jī)號(hào) 15 條樣本按「連續(xù) / 帶分隔符 / 全角或帶前綴」三類各 5 條同上腳本的 SAMPLES 字典1.2、2.1R1 原樣 9/1560.0%歸一化后 10/1566.7%同上日志「手機(jī)號(hào)召回」段2.1R2 原樣 14/1593.3%歸一化后 15/15同上日志「手機(jī)號(hào)召回」段2.1、4.16 條正常字段共 11 次誤判批次號(hào)與商品條碼未被誤判同上日志「正常字段誤判」段第 3 章身份證規(guī)則 5/5末位小寫 x 需[\dXx]才命中同上日志「其他關(guān)鍵點(diǎn)」段2.2銀行卡規(guī)則 3/5且吃掉 5 條 18 位身份證同上日志「其他關(guān)鍵點(diǎn)」段2.2郵箱規(guī)則 5/5本輪無(wú)誤判同上日志命中矩陣2.3\d在 Unicodestr模式下匹配任何 Unicode 十進(jìn)制數(shù)字含全角Python 3 文檔 re 模塊Python Software Foundationhttps://docs.python.org/3/library/re.html4.1\b為詞邊界「詞」在 Unicode 模式下指 Unicode 字母數(shù)字加下劃線同上附表 B第五十一條第三項(xiàng)采取相應(yīng)的加密、去標(biāo)識(shí)化等安全技術(shù)措施《中華人民共和國(guó)個(gè)人信息保護(hù)法》全文中央網(wǎng)絡(luò)安全和信息化委員會(huì)辦公室 2021-08-20 發(fā)布https://www.cac.gov.cn/2021-08/20/c_1631050028355286.htm7.1錨點(diǎn)版正則、豁免清單、關(guān)鍵詞窗口為本文改進(jìn)寫法未在本機(jī)腳本中實(shí)跑本文作者改寫對(duì)應(yīng)代碼塊上方已標(biāo)注待驗(yàn)證提示4.2、6.1附表 B術(shù)語(yǔ)速查表術(shù)語(yǔ)一句話解釋在本文哪里用到脫敏把敏感字段替換、遮蔽后再落盤或外發(fā)的動(dòng)作第 1 章開(kāi)頭正則用一串符號(hào)描述「什么樣的字符串算命中」的規(guī)則文本1.1召回該抓到的里面實(shí)際抓到了多少2.1誤判不該動(dòng)的正常字段被動(dòng)過(guò)了第 3 章歸一化比對(duì)之前先把不同寫法統(tǒng)一成一種形式這里指全角轉(zhuǎn)半角4.1錨點(diǎn)在規(guī)則兩頭加「前后必須是什么」的約束4.2負(fù)向斷言錨點(diǎn)的一種寫法要求「前后不能是什么」如(?!\d)4.2關(guān)鍵詞窗口要求敏感詞出現(xiàn)在匹配位置前方有限字符數(shù)內(nèi)的約束4.3豁免清單已知的正常長(zhǎng)數(shù)字匹配前先掛號(hào)脫敏時(shí)跳過(guò)6.1掩碼用星號(hào)等字符替換敏感片段的做法6.1冪等同一段文本處理兩次結(jié)果和一次一樣6.2去標(biāo)識(shí)化讓信息在不借助額外信息的前提下無(wú)法指向特定個(gè)人7.1寫在最后這篇用到的資料寫這篇文章時(shí)把相關(guān)的官方文檔和源碼又翻了一遍順手也整理了幾份配套的東西大模型學(xué)習(xí)路線圖從零基礎(chǔ)到能自己動(dòng)手做 Agent按階段說(shuō)明每一步該學(xué)什么、哪些可以先跳過(guò)《LangChain LangGraph MCP 智能體開(kāi)發(fā)實(shí)戰(zhàn)》視頻課7 個(gè)模塊從私有化部署、EmbeddingRAG 到 MCPAgent 全流程AI 大模型知識(shí)庫(kù)在線可查Agent Skills 從入門到落地、Claude Skills 完全指南等專題按目錄瀏覽即可640 套 AI 大模型行業(yè)報(bào)告 經(jīng)典 PDF 書籍看行業(yè)落地案例和別人怎么做的時(shí)候用得上大模型零基礎(chǔ)到精通教學(xué)視頻跟著敲一遍比只讀文檔快得多資料是我自己整理的放在下面這個(gè)碼上掃碼即可獲取添加時(shí)備注「AI」優(yōu)先通過(guò)。資料按「先路線、再動(dòng)手、最后查漏」的順序整理好了建議先看學(xué)習(xí)路線那一份照著它挑一條適合自己當(dāng)前基礎(chǔ)的路徑再往下看。