正則表達解析 Markdown 語法
轉載請註明出處
原文連線 http://blog.huanghanlian.com/article/5c80b4176f8b011040530140
文章起源
源於本部落格開發實現需要
head
Markdown 是一種可以使用普通文字編輯器編寫的標記語言,通過簡單的標記語法,它可以使普通文字內容具有一定的格式。
真實場景以及功能需求
- 文章編寫
- 文章列表預覽
- 頭部描述擷取
需要做的事情是將文章Markdown 語法的字串,對特定的語句進行過濾。只顯示文章正文部分
實現場景
文章編寫存入資料庫是字串型別
在訪問某篇文章後臺會去資料庫中取對應的文章資料。
然後通過匹配將Markdown 語法的字串轉義成html元素字元渲染輸出
'# 一級標題\r\n## 二級標題\r\n##### 五級標題\r\n- 列表第一項\r\n- 列表第二項\r\n1. 有序列表第一項\r\n2. 有序列表第 二項\r\n[標題](連結地址)\r\n\r\n*斜體*\r\n**粗體**\r\n> 引用段落\r\n```\r\n程式碼塊\r\n```'
現在需要做的是將這些字元去掉不想要的,提取內容部分
正則表示式規則
在使用正則表示式解析 Markdown 語法之前,我們要先對正則表示式的規則有一個基本的認識,下面我整理了一張正則表示式語法對照表。
正則表示式預定義類:
字元 | 含義 |
---|---|
. | 除了回車符和換行符之外的所有字元,等價於 |
d | 數字字元,等價於[0-9] digit |
D | 非數字字元,等價於 |
s | 空白符,等價於[tnx0Bfr] space |
S | |
w | 單詞字元(字母,數字,下劃線),等價於[a-zA-Z_0-9] word |
W | 非單詞字元,等價於 |
邊界
字元 | 含義 |
---|---|
^ | 以xxx開始 |
$ | 以xxx結束 |
b | 單詞邊界 |
B | 非單詞邊界 |
量詞
字元 | 含義 |
---|---|
? | 出現零次或一次(最多出現一次) |
+ | 出現一次或多次(至少出現一次) |
* | 出現零次或多次(任意次) |
{n} | 出現n次 |
{n,m} | 出現n到m次 |
{n,} | 至少出現n次 |
正則表示式解析 Markdown 語法
Markdown 語法包括標題、圖片、連結、引用塊、列表、粗體、斜體等,下面是解析這些語法的正則表示式和簡單說明:
- 標題(表示以一個或多個“#”開頭的字串,並且“#”之後有0個或以上的字元,如:“### 三級標題”)。
^(#+)(.*)
- 連結 (在 Markdown 語法中連結的表示形式為
[連結](URL)
。)。
/\[[\s\S]*?\]\([\s\S]*?\)/g
解釋:
匹配 [
符 開始
緊接著[sS]範圍類 空白符或者非空白符都可以的類。
*
代表出現0次或者無限次
?
非貪婪模式
讓正則表示式儘可能少的匹配,也就是說一旦匹配成功匹配不再繼續嘗試,就是非貪婪模式。
做法很簡單,在量詞後面加上?即可。
- 斜體(表示以一個 * 或者 _ 開頭並結尾(\1表示規則和第一個集合相同),中間包含0個或多個字元的字串)。
(\\*|_)(.*?)\\1
- 圖片(部分地方同連結)
!\\[[^\\]]+\\]\\([^\\)]+\\)
- 粗體(同斜體)
(\\*\\*|__)(.*?)\\1
- 刪除線(刪除線)
\\~\\~(.*?)\\~\\~
- 引用塊
\n(>|\\>)(.*)
- 內聯程式碼塊
{1,2}[^`](.*?)`{1,2}
- 分割線
^-+$
-
`
包圍的程式碼塊
``([\\s\\S]*?)```[\\s]?
- 無序列表
^[\\s]*[-\\*\\+] +(.*)
- 有序列表
^[\\s]*[0-9]+\\.(.*)
function abstractFn(res){ if(!res){ return ''; }else{ var str=res.replace(/(\*\*|__)(.*?)(\*\*|__)/g,'')//全域性匹配內粗體 .replace(/\!\[[\s\S]*?\]\([\s\S]*?\)/g,'')//全域性匹配圖片 .replace(/\[[\s\S]*?\]\([\s\S]*?\)/g,'')//全域性匹配連線 .replace(/<\/?.+?\/?>/g,'')//全域性匹配內html標籤 .replace(/(\*)(.*?)(\*)/g,'')//全域性匹配內聯程式碼塊 .replace(/`{1,2}[^`](.*?)`{1,2}/g,'')//全域性匹配內聯程式碼塊 .replace(/```([\s\S]*?)```[\s]*/g,'')//全域性匹配程式碼塊 .replace(/\~\~(.*?)\~\~/g,'')//全域性匹配刪除線 .replace(/[\s]*[-\*\+]+(.*)/g,'')//全域性匹配無序列表 .replace(/[\s]*[0-9]+\.(.*)/g,'')//全域性匹配有序列表 .replace(/(#+)(.*)/g,'')//全域性匹配標題 .replace(/(>+)(.*)/g,'')//全域性匹配摘要 .replace(/\r\n/g,"")//全域性匹配換行 .replace(/\n/g,"")//全域性匹配換行 .replace(/\s/g,"")//全域性匹配空字元; return str.slice(0,155); } }