2014年8月7日 星期四

line-singularize : 網頁內的指定清單/列表「單列化」以便利 regexp 後續加工

這一篇文章的主角其實並不是 regular expressions, 但是可能只有那些平時有在用 regexp 的朋友才會覺得有用。 面對大量的文字格式 (html/xml) 條列資料時, 經常只需要一個 perl 的 regexp 命令, 就可以把它捏成你要的格式 -- 例如把一個網頁裡面的條列資料變成可以匯入試算表或資料庫軟體的格式。 但是 regexp 處理資料時, 原則上 以列為單位 比較好處理。 (其實 perl 也有 -000 的選項可以處理 「以段為單位」 的資料, 不過還是比較麻煩。) 所以我用 php + querypath 寫了一支小程式 line-singularize 把 html/xml 當中的某些指定資料變成每筆一列, 以利後續餵給 perl -ne 或 perl -pe 處理。

請先確認你已安裝命令列版的 php (debian: php5-cli 套件) 及 querypath 函式庫 (我用的還是 2.1.2 版)。 下載/存檔 line-singularize 之後, 記得開放執行權限。 以下是一些使用範例:

  1. ./line-singularize -f 2013.php -s 'ul.plurk li' > 2013-singularized.php 把我 2013 年噗過的每一條噗浪各自濃縮成一列。
  2. ./line-singularize -f talk.php -s '#content #talk li' > talk-singularized.php 把我的每一筆演講記錄各自濃縮成一列。
  3. ./line-singularize -f favourites.gpx -s 'wpt' > favourites-singularized.gpx 把我 osmand 的每一筆 「我的最愛地點」 各自濃縮成一列。
  4. ./line-singularize -f large-pkg-dep.svg -s 'g polygon' > large-pkg-dep-singularized.svg 把一個 svg 向量圖檔裡面的每個多邊形定義各自濃縮成一列。

這個指令會到輸入資料檔裡面, 依據一個 css selector 找到符合條件的所有元素, 把每個元素裡面的換列都改都改成空格, 也就是把每個元素濃縮在一列上面。 它接受以下選項:

  1. -f 指定輸入檔名。 (必填選項)
  2. -s 指定 css selector 作為搜尋條件。 (必填選項)
  3. -t 指定要把這個檔案當成 html 或是 xml 格式來處理。 沒有指定這個選項的話, 就根據副檔名自動猜測。 如果副檔名是 .htm .html .php , 就當作 html 檔處理; 其餘狀況都當作 xml 檔處理。
  4. -v 囉嗦程度。

每次執行 line-singularize 時, 會印出一列除錯訊息, 詳述它所看到的參數。 如果出現一大串錯誤訊息, 請先回頭檢查一下第一列除錯訊息, 看是否檔案格式被判斷錯誤等等。 如果不想看見這一列除錯訊息, 就在命令列上指定 -v 0

從此以後, 你就可以同時享用兩個世界 (querypath 跟 regexp) 最美好的部分了!

順便一提: 如果你想學寫 querypath 程式, 這應該也是一個很短很容易讀的入門範例。 程式前面一大半主要在判斷到底應該把輸入資料當成 html 還是 xml 來處理。 主迴圈很簡單: 把符合條件的元素一一抓出來, 轉成文字格式並且去除換列字元。 再回頭把原先的舊元素標上一個自己隨便發明的 tag。 (以便將來可以透過這個 tag 把所有的舊元素一口氣刪掉。) 最後把已去除換列字元的文字轉變成一個新元素加到舊元素的後面去。 因為使用 querypath 的時候, 每個動作都會讓它改變目前的「目光焦點」, 所以最後要印出新版的檔案時, 記得要用 top() 把目前「目光焦點」移到最上面 (root element)。 大推 這篇文章 的簡單明瞭插圖。

沒有留言:

張貼留言