2013年11月1日 星期五

如何用 Javascript 將過長字串分行

最近工作上要將作業程序自動化, 主要是從系統吐出的資料庫資訊, 製作資料異動指令, 然後交由軟體機器人自動執行指令. 譬如系統吐出如下內容 :

251 N 0 1 DRTER K 0 115 N Y 342 RETURN 11 TAK R 2 SETCDN M N 0 0 1 $ $

很奇怪的資料庫紀錄吧? 是的, 這是我胡謅的, 因為這兩天去上 HTML5 的課, 不在辦公室. 但心裡還在想著如何搞定這程式, 所以就弄個類似資料來測試. 這任務是要把上面紀錄裡的某些欄位修改後, 前面冠上 upd 指令來更新紀錄, 例如把 RETURN 改成 BLOCK 好了, 那麼要對系統下的指令便是 :

UPD 251 N 0 1 DRTER K 0 115 N Y 342 BLOCK 11 TAK R 2 SETCDN M N 0 0 1 $ $

但上面的 UPD 指令會執行失敗, 因為這系統有個規矩, 就是對它所下的指令, 每行不能超過 20 個字元, 超過的話, 必須斷行, 每行以 + 符號串接, 而且斷行時欄位必須完整, 不能把一個欄位值硬生生攔腰截斷, 譬如若 BLOCK 的 O 剛好在第 20 個字元, 你不能把 BLO 與 CK 拆在不同行, 必須把 BLOCK 整個放到下一行才行.  斷行方式可能很多, 總之, 不含 + 串接符, 每行不要超過 20 字元就好了. 例如像下面這樣的格式即可 :

UPD 251 N 0 1 DRTER +
K 0 115 N Y 342 +
BLOCK 11 TAK R 2 +
SETCDN M N 0 0 1 $ $

這該如何處理呢? 趁上課空檔斷斷續續寫了程式碼來測試, 最後寫成一個函式來呼叫, 因為專案中還會再用到. 這裡原字串用空格作為斷行點, 設定每 10 個字元開始尋找下一個空格作為斷行點, 這是因為每個欄位值之長度都不會超過 10 個字元, 因此阿搜比有 10 個字元的餘裕應該 OK, 這是可以視實際其況自由調整的 (所以才要寫成函式啊) :

  var str="251 N 0 1 DRTER K 0 115 N Y 342 RETURN 11 "  + 
               "TAK R 2 SETCDN M N 0 0 1 $ $";
  var arr=strwrap(str.replace(/RETURN/g, "BLOCK")," ",10);
  var cmd=arr.join(" \+\r\n");
  alert(cmd);
  function strwrap(str,d,wrap) { //str=原字串, d=分隔字串, wrap=斷行字元數
    if (str.length > wrap) { //超過分段長度
        var s=0;    //頭指標初值
        var e=wrap; //尾指標初值
        var arr=new Array(); //暫存各斷行子字串
        do { //以迴圈找尋分隔字串,利用頭尾指標斷行
            e=str.indexOf(d, e); //從尾指標開始找到分隔字元,以其更新尾指標
            if (e==-1) { //後面已找不到分隔字串了
                var sub=str.substring(s, str.length); //斷行到字串尾即可
                arr.push(sub); //最後一個斷行子字串存入陣列
                break; //跳離迴圈
                } //end of if
            var sub=str.substring(s, e); //斷行子字串
            arr.push(sub);  //將斷行子字串放入陣列
            s=e + d.length; //移動起點至分隔字串尾之下一位置
            e=s + wrap;     //移動預估終點至預定分割長度
            }
        while (s < str.length);  //頭指標尚未超過字串尾還要再進迴圈        
        } //end of if
    else {var arr=new Array(str);} //不須斷行,傳回單元素陣列
    return arr;
    }



沒有留言 :