2015/5/24

[Regex] 正規表示式的應用

許多人很害怕 Regular Expressions, 除了它的確不好學之外, 主要是因為大家普遍不太了解它能拿來做什麼。所以我在這裡要陸續舉出一些實際上的應用範例, 向讀者們示範 Regular Expression 在實際生活中能幫我們解決什麼問題。依照我的慣例, 當我想到什麼, 就會在原來的文章裡直接修改, 不另做通知, 也不會再寫另一篇新的文章

如果你完全不懂 Regular Expression, 我建議你先去讀一下我寫的入門教學「[Regex] Regular Expression 詳論」。

在使用的工具方面, 我仍然最推薦 Sublime Text 3, 其次是 Visual Studio, 或者最新流行的 Visual Studio Code。此外, 其實 Word 本身也內建了跟 Regex 有點類似的所謂「萬用字元」搜尋與取代工具; 如果真的有需要, Regex 是派得上用場的。

或許讀者覺得奇怪, 為什麼我在系列文章裡介紹的是 .Net 的 Regex, 但偏偏推薦使用 Python 的 Regex 引擎的 Sublime Text 作為首選工具呢? 這是因為 Sublime Text 的搜尋與取代工具可以讓我們很方便地處理斷行字元; 我們甚至可以把好幾行一起拷貝到搜尋與取代工具的文字方塊裡頭去, 如此, 我們可以處理跨行的文字取代作業。其實在某個程度上 Visual Studio 也辦得到 (使用 [\s\r\n]* 取代斷行字元), 但是如果單就文字處理方面, 在操作的方便性上, 我個人覺得 Sublime Text 還是略勝一籌。

不過, 相對的, Sublime Text 缺少了方塊狀選取 (alt-滑鼠按鍵) 的功能, 這方面就屬 Visual Studio 獲勝了 (連 VS Code 也沒有這功能)! 所以實際上我個人是這兩個工具都搭配使用的, 缺一不可。

例一. XML 元素置換

首先, 我來舉一個最具代表性的 Regex 應用。假設我有一個 XML 文件如下:

<?xml version="1.0" encoding="utf-8" ?>
<document version="1">
  <item>
    <number>1</number>
    <content>blah blah</content>
  </item>
  <item>
    <number>2</number>
    <content>blah blah</content>
  </item>
  <item>
    <number>3</number>
    <content>blah blah</content>
  </item>
  ...
</document>  

由於某種原因, 我打算把這個文件寫成 HTML 相容格式, 讓它可以直接在網頁上直接呈現, 卻不必寫 XSLT。我們可以怎麼做?

至少有兩種方式可以馬上辦到。第一種, 把 <document> 和 </document> 標籤改成 <ol> 和 </ol>, 再把所有 <number> 元素刪除, 再把所有 <item> 和 </item> 改成 <li> 和 </li>, 把所有 <content> 和 </content> 改成 <span> 和 </span>, 結果如下:

<?xml version="1.0" encoding="utf-8" ?>
<ol version="1">
  <li>  
    <span>blah blah</span>
  </li>
  <li>    
    <span>blah blah</span>
  </li>
  <li>    
    <span>blah blah</span>
  </li>
  ...
</ol>  

如果使用 VS 或 Sublime Text 的話, 只需按下幾次 Ctrl-H, 做幾次置換動作, 就可以很快做好。其中要把所有 <number> 元素刪除的方法也很簡單, 啟用 Regex Expression 選項, 在「搜尋詞彙」或 "Find What" 字方塊中填入 "<number>\d*</number>" (不含引號), 另一個方塊保持空白, 就可以一次把所有該元素清除。至於它可能遺留的一個空行, 如果你看不順眼的話, 請讀者自己想辦法把它刪除, 方法其實我上面已經提示過了。

以上這種方法看來簡單快速, 但是它事實上把所有 number 元素清除了。如果你想把它留著, 怎麼辦? 在這種情況下, 我們可以這麼做: 

Replace with Regex

如上圖所示, 找出第一組數字和第二組文字, 再填入被取代文字內, 結果如下:

<?xml version="1.0" encoding="utf-8" ?>
<ol version="1">
  <li>
    <span number="1">blah blah</span>
  </li>
  <li>
    <span number="2">blah blah</span>
  </li>
  <li>
    <span number="3">blah blah</span>
  </li>
  ...
</ol>

如此, 這段文字不但可以當作 HTML 正常顯示, 也可以當作 XML 文件, 將裡面的數字取出。

如果你覺得你不想把這組數字塞進 attribute 裡, 而想讓它維持為 element 的話, 那麼你可以回到上一個方法, 把它變成 "<script>1</script>" 這樣的型式。那麼這段標籤既是標準的 XML 元素, 也不會顯示在網頁上。

在 Sublime Text 中第一組 matched 是以 \1 表示, 第二組則以 \2 表示; 如果你使用的是 Visual Studio, 它是以 $1 和 $2 表示, 依此類推。

像這類的文字取代作業, 雖然在我的範例中只有三個項目要處理, 但是實際上我們經常可以遇到成百上千個項目; 如果沒有 Regex 工具可用, 那可就變成十分惱人的問題了。所以 Regex 實在是開發人員不能不熟的一項必備技能!

相關主題

 

沒有留言:

張貼留言