正規表示式提取 git 提交記錄中的新增程式碼行

Dushusir發表於2022-04-14

原文:https://lwebapp.com/zh/post/r...

需求

最近有小夥伴提了個需求,想用正規表示式從一段 git 提交記錄中提取出具體更新了哪些程式碼,簡單來說就是 commit diff 展示的程式碼,需要把 程式碼前面帶 +- 的行剝離出來。

我們從 RichX 專案複製出來一段提交記錄,稍作修改用於演示。

+ import { Plugin } from "..";
- CONST SUM = NUM_A + NUM_B;
+ CONST SUM_ALL = NUM_A + NUM_B;

  export const DEFAULT_RICH_TEXT = {
-   text: "Simple Rich Text Demo",
+   config: "Simple Rich Text Demo",
    setting: [],
  };

  export type ObjectKV<V = object> = {
    [key: string]: V;
  };

+ export interface IPlugins {
+   [key: string]: Plugin;
+ }

我們把需求轉換下,就是正則匹配多行文字中以 +- 開頭的行。

解法一

思路:

  1. 首先匹配 + 開頭的字元:\+.*
  2. 然後帶上 -(\+|\-).*
  3. 因為多行文字之間是有換行符分割的,所以 + 開頭的單行文字的前面一個字元,就是上一行最後的換行符 \n,同樣的,這一行的結尾也是換行符。所以我們利用正則斷言,將兩個換行符匹配目標文字的首尾即可:(?<=\n)(\+|\-).*(?=\n)
  4. 最後還要考慮兩個特殊情況,整個文字的首尾位置。首位沒有上一行所以匹配不到換行符 \n,只能匹配開頭 ^,結尾後面也可能沒有換行符,用 $ 代替:(?<=^|\n)(\+|\-).*(?=\n|$)

程式碼:

const content = `+ import { Plugin } from "..";
- CONST SUM = NUM_A + NUM_B;
+ CONST SUM_ALL = NUM_A + NUM_B;

  export const DEFAULT_RICH_TEXT = {
-   text: "Simple Rich Text Demo",
+   config: "Simple Rich Text Demo",
    setting: [],
  };

  export type ObjectKV<V = object> = {
    [key: string]: V;
  };

+ export interface IPlugins {
+   [key: string]: Plugin;
+ }`

content.match(/(?<=^|\n)(\+|\-).*(?=\n|$)/g)

// 輸出陣列
// 0: "+ import { Plugin } from \"..\";"
// 1: "- CONST SUM = NUM_A + NUM_B;"
// 2: "+ CONST SUM_ALL = NUM_A + NUM_B;"
// 3: "-   text: \"Simple Rich Text Demo\","
// 4: "+   config: \"Simple Rich Text Demo\","
// 5: "+ export interface IPlugins {"
// 6: "+   [key: string]: Plugin;"
// 7: "+ }"

解法二

思路:

上面的方案要自己匹配換行符,有點麻煩。我們可以省去自己判斷換行符的步驟,直接匹配每一行的首尾,再使用正規表示式標誌 m 啟用多行匹配模式:/^(\+|\-).*$/gm

程式碼:

const content = `+ import { Plugin } from "..";
- CONST SUM = NUM_A + NUM_B;
+ CONST SUM_ALL = NUM_A + NUM_B;

  export const DEFAULT_RICH_TEXT = {
-   text: "Simple Rich Text Demo",
+   config: "Simple Rich Text Demo",
    setting: [],
  };

  export type ObjectKV<V = object> = {
    [key: string]: V;
  };

+ export interface IPlugins {
+   [key: string]: Plugin;
+ }`

content.match(/^(\+|\-).*$/gm)

// 輸出陣列
// 0: "+ import { Plugin } from \"..\";"
// 1: "- CONST SUM = NUM_A + NUM_B;"
// 2: "+ CONST SUM_ALL = NUM_A + NUM_B;"
// 3: "-   text: \"Simple Rich Text Demo\","
// 4: "+   config: \"Simple Rich Text Demo\","
// 5: "+ export interface IPlugins {"
// 6: "+   [key: string]: Plugin;"
// 7: "+ }"

總結

以上就是和小夥伴一起探討出的一點寫正規表示式的經驗,主要學習了斷言和多行匹配標誌。這裡的案例還比較簡單,後續有更深入使用案例再和大家分享,歡迎關注我們的更新 #regex

參考

相關文章