效率提升之正則替換

引言:讓文本處理不再是體力活

作為程序員,我們每天都在與代碼、日誌、配置文件打交道。有時候,面對成百上千行需要處理的文本,即便是最強壯的"複製粘貼大師"也會感到力不從心。
所以,今天我要分享一個在日常工作中經常用到的文本處理技巧——正則替換。

  • 你是否曾經為了從幾百行日誌中提取用户ID而一個個複製粘貼?
  • 你是否曾經因為需要將一堆數據轉換成SQL語句而加班到深夜?
  • 你是否曾經面對重複的文本替換任務而感到人生無望?

如果你的答案是肯定的,那麼恭喜你,今天這篇文章將是你的救星!正則替換不僅能解決這些問題,還能讓你的工作效率提升到一個全新的高度。更重要的是,掌握這門技能後,你在同事眼中的形象將從"勤奮的碼農"一躍成為"高效的魔法師"。

接下來,我將帶你進入正則表達式的奇妙世界,從基礎示例到語法技巧,一步步掌握這門讓工作效率倍增的技能。

讓我們先來看看正則替換可以幫我們做什麼

場景一:從日誌中提取關鍵數據

比如:你需要從一堆日誌中提取所有用户ID。

原始日誌

2024-01-15 10:30:25 INFO [user_45678] Login successful
2024-01-15 10:31:12 ERROR [user_12345] Database connection failed
2024-01-15 10:32:05 WARNING [user_78901] Session timeout

正則表達式.+user_(\d+).+

替換表達式$1

替換結果

45678
12345
78901

我們用\[user_(\d+)\]匹配[user_數字]格式的文本,並捕獲其中的數字部分。替換時,我們只保留捕獲到的數字$1,就這樣輕鬆提取出了所有用户ID!

繼續處理:現在我們需要將它們轉換為SQL的IN語句參數。

原始數據

12345
67890
11223

正則表達式(\d+)\n?

替換表達式'$1',

替換結果

'12345','67890','11223',

然後你只需要手動去掉最後一個逗號,包裹在IN()中就完成了:

select * from user WHERE user_id IN ('12345','67890','11223')

另一種方式:同樣是這個數據,如果我們想把它直接變為多條sql

原始數據

12345
67890
11223

正則表達式(\d+)

替換表達式select * from user where user_id = '$1';

替換結果

select * from user where user_id = '12345';
select * from user where user_id = '67890';
select * from user where user_id = '11223';

場景二:清理CSV數據中的多餘空格

身經百戰的你一定遇到過這樣的文件——字段之間要麼擠成一團,要麼像被狗啃過一樣到處是空格。這種"格式混亂症"不僅影響閲讀,還會讓你的數據導入工具崩潰給你看。

原始CSV數據

ID  ,  用户名  ,  部門     ,  入職日期
123,   張三  ,  技術部     , 2023-01-15  
456  ,李四,市場部,  2022-07-20
789   ,王五,  設計部  ,2021-11-10

有些逗號前有空格,有些逗號後有空格,有些兩邊都有空格。手動清理?別開玩笑了,幾百行數據能讓你清理到懷疑人生。

正則表達式\s*,\s*

  • \s*:匹配零個或多個空白字符(包括空格、製表符)
  • ,:匹配逗號本身
  • 組合起來就是:匹配任何前後帶有零個或多個空格的逗號

替換為,(一個乾淨利落的逗號)

替換後的結果

ID,用户名,部門,入職日期
123,張三,技術部,2023-01-15
456,李四,市場部,2022-07-20
789,王五,設計部,2021-11-10

上面兩個例子都是相對比較簡單的場景,但是正則替換的強大之處在於它的靈活性和通用性。你可以根據實際需求,定製出各種複雜的匹配模式和替換規則。
下面我將介紹一些常用的正則表達式語法,幫助你快速上手。

正則表達式基礎語法

如果把文本處理比作一場尋寶遊戲,那麼正則表達式就是你的尋寶地圖。在正式開始尋寶之前,我們需要先學會看地圖上的標記。

單個字符匹配:最基本的語法

正則表達式的最基本操作就是匹配單個字符。比如,如果你想在文本中找到所有的字母"a",直接使用a就可以了。

匹配模式:a
匹配結果:在文本中找到所有的字母"a"

但有時候,我們需要匹配一類字符,這時候就需要用到字符類(Character Classes)。

  • [abc]:匹配字母a、b或c中的任意一個
  • [0-9]:匹配任意一個數字(也可以簡寫為\d
  • [a-zA-Z]:匹配任意一個大小寫字母

任意字符匹配:萬能鑰匙

如果你想匹配任何字符(除了換行符),可以使用.(點)。這是正則表達式中的萬能鑰匙

匹配模式:c.t
匹配結果:cat、cot、cut、c1t、c@t等(只要中間是任意單個字符)

開頭和結尾:精準定位

有時候,我們需要確定匹配內容必須出現在文本的開頭或結尾,這時候就需要用到錨點(Anchors)。

  • ^:匹配行的開頭
  • $:匹配行的結尾
匹配模式:^hello
匹配結果:只有以"hello"開頭的行才會被匹配

匹配模式:world$
匹配結果:只有以"world"結尾的行才會被匹配

匹配模式:^hello world$
匹配結果:只匹配整行內容就是"hello world"的行

數字和非空字符:特殊的類型

除了字符類,正則表達式還提供了一些特殊的簡寫來匹配常見的字符類型:

  • \d:匹配任意數字(等價於[0-9]
  • \D:匹配任意非數字字符(等價於[^0-9]
  • \w:匹配任意字母、數字或下劃線(等價於[a-zA-Z0-9_]
  • \W:匹配任意非字母、數字、下劃線的字符
  • \s:匹配任意空白字符(空格、製表符、換行符等)
  • \S:匹配任意非空白字符(也就是我們常説的"非空字符")
  • \n:匹配換行符

出現次數:數量不是問題

在正則表達式中,我們可以指定某個字符或組出現的次數,這讓我們的匹配更加靈活。

-*:匹配前面的字符零次或多次("要多少有多少")
-+:匹配前面的字符一次或多次("至少要有一個")
-?:匹配前面的字符零次或一次("可有可無")
-{n}:匹配前面的字符恰好n次
-{n,}:匹配前面的字符至少n次
-{n,m}:匹配前面的字符至少n次,最多m次

使用括號()捕獲數據

最神奇的部分來了!使用括號()可以捕獲匹配到的數據,然後在替換時使用。這是正則替換中最核心、最強大的功能之一。

當你使用括號包圍一部分正則表達式時,這部分匹配到的內容會被"捕獲"並保存起來。你可以用$1$2$3等來引用這些捕獲的內容,順序與括號出現的順序一致。

字符:1993-01-29
匹配模式:(\d{4})-(\d{2})-(\d{2})
捕獲組:$1=1993,$2=01,$3=29

現在,你已經掌握了正則表達式的基本概念,但是仍然需要通過更多的實戰才能熟練運用它!
回頭看看前面的幾個示例,是不是已經完全可以看懂了?

正則表達式雖然還有更多高級複雜的用法,但是你只需要掌握上面的部分就已經能處理日常工作中的大部分文本問題了