原文:https://lwebapp.com/zh/post/regular-expression-to-match-multiple-lines-of-text
需求
最近有小伙伴提了個需求,想用正則表達式從一段 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;
+ }
我們把需求轉換下,就是正則匹配多行文本中以 +
和 -
開頭的行。
解法一
思路:
- 首先匹配
+
開頭的字符:\+.*
- 然后帶上
-
:(\+|\-).*
- 因為多行文本之間是有換行符分割的,所以
+
開頭的單行文本的前面一個字符,就是上一行最后的換行符\n
,同樣的,這一行的結尾也是換行符。所以我們利用正則斷言,將兩個換行符匹配目標文本的首尾即可:(?<=\n)(\+|\-).*(?=\n)
- 最后還要考慮兩個特殊情況,整個文本的首尾位置。首位沒有上一行所以匹配不到換行符
\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。