echo Impossible|sed 's/Im/To be /'

August 03, 2008

TChinese text written vertically

前言:
要當孝子還真得要精通十八般武藝,老媽又出難題給我,善書歌謠要直式列印不要橫式。 橫的列印年長的長輩看不慣,也看不懂。好吧....科技來自於人性,想辦法吧。

我長期使用 docbook, 跟 kword 排版列印,這次真的踢到鐵板了。kword 找不到直式排版跟列印, OpenOffice oowriter 有找到提示但試不出來。再消耗了數個小時候,夜深了,再耗下去天亮肯定 甭想上班了。本想找翻箱倒櫃找史前時代前人所寫的 big5 text ttf to ps ... ,它是個用 big5 text 加上類似倚天列印控制碼,透過程式取得 ttf 中文字型轉成中文字 ps 描述,排版後再轉成 ps file, 橫書直書跟套表列印都相當好用。

正要發動 google 找時,才想到 cjk-latex 中文直書有範例可抄,感謝 debian 讓安裝 cjk-latex 變得如此容易。我也再 30 分鐘後順利的產生出老媽要的直式列印的善書歌謠 pdf 檔,我終於保住了 我的睡覺時間,感謝 latex。

現在是怎樣,文字模式比圖形介面來的好用了嗎? XD

現在的 cjk-latex 已經採用 utf8 編碼了,不用再像以前一樣還要個 big5-latex 轉碼後再處理。 latex 果然是值得信賴的伙伴。

直式列印的善書歌謠 pdf 檔
直式列印的善書歌謠 tex 檔

June 28, 2008

[tip] Transfer compression wave file to uncompression.

前言:
最近老媽社交能力火力全開,由外面搜刮了一大堆錄音帶。多次購入廉價錄音機經常發生卡帶現象。 大費周張將錄音帶用 mp3 轉錄成 wave 檔,但 mp3 player 螢幕,字型,按鍵都太小,操作對 年長的長輩實在是太不友善了,只好想法子轉成 audio CD。

mp3 player 所錄製下來的 wave 檔,用 wave 剪接軟體 (mhwaveedit) 或是 k3b 燒錄 audio CD, 被一直 抱怨是 compressed wave file 而不能使用。兩者均強調剪接及燒錄需要 uncompressed wave file。 問 google 關鍵字可能用的不好也沒有好答案。想想透過 mplayer 或 mencoder 轉檔看可不可行。 沒想到 man 後答案就出來了。

110碼:AAA2369 $> file *.WAV
23-10625M001.WAV: RIFF (little-endian) data, WAVE audio, IMA ADPCM, mono 44100 Hz
...
110碼:AAA2369 $> for i in *.WAV; do mplayer -vo null -ao pcm:file=${i/WAV/wav} $i; done
...
110碼:AAA2369 $> file *.wav
23-10625M001.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, mono 44100 Hz
110碼:AAA2369 $>
經過處理後之後這些檔案就都可以剪接跟燒錄了,好佳在不需重新錄音。但後遺症來了,我光碟燒到手抽筋,老媽將它 當成禮物送人。苦啊。

June 22, 2008

[tip] Using template rewrite configuration file working with shell.

概要:
設定檔的欄位增刪一直以來是個痛,這會隨著時間的累積而越來越難以處理。寫程式時預先假設變數可能是 空變數給定一個預設值是個好習慣,但變數寫回設定檔,判別可能存在或不存在,移除過期或是新增,這都 讓問題複雜化。Keep simple and stupid,以下提供一個 simple and stupid 的方法供參考。

這是在工作中衍生出來的實戰技巧,只需要確認標準設定檔格式以及變數,以他為範本重建過期 且雜亂無章的設定檔,本機設定的變數可被保留,新增刪除過期變數也可輕易達成。

# 程式
$> cat rebuild_conf.sh
#!/bin/sh
. conf.default
. conf.current

IFS=''
CONF=$(cat conf.default | sed -e '/^[^#]/s/\(^.*\)=.*$/\1=\\"$\1\\"/; /^#/s/"/\\"/g')
eval 'echo ' \"$CONF\" '| cat > conf.rebuild '

# 樣版設定檔,注意新增的欄位
$> cat conf.default
# host area
hostname="AAA2369"
ipaddress="192.168.1.0"

# new add item
new_item="六  6月  7"
new_item1="13:44:11"
new_item2="CST 2008"

# color type : color="yellow|white|black"
#              color_type="mix|remix"
color="yellow"
color_type="mix"

# 在機器上使用已久的設定檔,注意過期跟重複的
$> cat conf.current
hostname="110碼"
ipaddress="10.0.0.1"
color="white"

# this item will be remove.
color_BeRemove="no thing"

color_type="remix"

color="yellow"
color="black"
ipaddress="10.0.0.254"

# 依照樣版重建設定檔,比對新增,及變數值
$> sh rebuild_conf.sh
$> cat conf.rebuild
# host area
hostname="110碼"
ipaddress="10.0.0.254"

# new add item
new_item="六  6月  7"
new_item1="13:44:11"
new_item2="CST 2008"

# color type : color="yellow|white|black"
#              color_type="mix|remix"
color="black"
color_type="remix"

這個技巧重建了設定檔,確保新增的變數可以有值,過期不要的又可以丟棄,本機設定可以保留, 檔案格式美觀可以閱讀。只需在開機或需要時做一次,就可以重建設定檔掌握變數。

June 07, 2008

[tip] lftp 內建的邏輯判斷

概要:
自動化或程式化上常需要邏輯判斷 if; else; && || , 再此介紹 lftp 較少人知道的邏輯判斷符號, && ||。

lftp 功能強大,內建多模組,依不同協定啟用不同模組 http, ftp, ssh。 lftp 可以自行撰寫 modules,透過動態載入模組啟用。 lftp 可使用 pipe line 的功能也很特別,配合 less more 瀏覽查尋很好用 ,output files name tree 再加工處理成 lftp script 讓 lftp 批次傳檔。 lftp mirror 可 download 也可 upload,總而言之一整個優。

lftp 有 && 跟 || 可用,用法跟 bash 一樣。

Bash
$> ls /nodir && echo OK || echo error
ls: 無法存取 /nodir: 沒有此一檔案或目錄
error
$> ls /etc/passwd && echo OK || echo error
/etc/passwd
OK
lftp 
$> lftp ftp://ftp.nsysu.edu.tw/
cd Linux && cd .. || echo error
cd ok, cwd=/Linux
cd Nodir && cd .. || echo error
cd: Access failed: 550 /Nodir: No such file or directory
error
cd Nodir && cd .. || !echo error > /tmp/log
cd: Access failed: 550 /Nodir: No such file or directory
cd Nodir && cd .. || quit
cd: Access failed: 550 /Nodir: No such file or directory
$>

June 07, 2008

proftpd iconv

概要:由 proftpd 提供動態檔名編碼轉換。Proftpd UTF8 <-> [ BIG5 | shift-jis | UTF8 ] Ftp Client

前情:開發 web ap,須上傳多個超大 video 檔案,利用 WinXP IE browser ftp 功能, 而衍生出 [BIG5|shift-jis|UTF8] <-> UTF8 的問題。中文 WinXP 內建的 ftp 上傳檔案 中文檔名會是 Big5 編碼。 遠端系統編碼是 UTF8,所以想簡單的透過 ftp server 更改檔名編碼,於是我找上了 ProFTPD - iconv() charset conversion patch 利用這個 patch 作 Big5 與 UTF8 轉換。如果故事就這樣結束了,那這篇也沒有存在的價值了。

問題:圖說如下

[1] WinXP ftp[Big5] <--> Linux Proftpd[Big5] <--> Linux lftp[Big5]
[2] WinXP ftp[Big5] <--> Linux Proftpd-iconv[UTF8] <--> Linux lftp[Big5]
[3] WinXP cutftp[UTF8] <--> Linux Proftpd[UTF8] <--> Linux lftp[UTF8]
[1] 三地檔名將會是 Big5, Big5 許功蓋會是個問題。
[2] 雖然 Linux Proftpd 端是 UTF8, 但 Linux lftp 卻又會是 Big5, 一樣有 Big5 的問題。
[3] 用可以選編碼的 ftp client 是最佳解,但不被接受,須額外安裝程式。

解法:
事實上這問題的解法相當多樣,簡單推算了一下,至少有六種。

  1. WinXP 透過 cutftp 上傳 UTF8 編碼的檔案。此解法最為簡單,但遭到否決,因為對使用者造成麻煩。
  2. 寫 WinXP ftp IE plugin。但卻遭到否決,因為對使用者造成麻煩,要安裝。
  3. WinXP 上傳 Big5 檔名, 在 Linux Proftpd-iconv patch 轉為 UTF8, 以千為數的 Linux lftp download video 會因 Proftpd-iconv path 再度將檔名轉為 Big5,須再度透過 iconv 在轉成 UTF8。
  4. 同上,但直接透過 lftp set file:charset , 或 set ftp:charset 轉碼。 現行案例有兩種以上可能的編碼 Shift-jis, GBK, Big5,這須額外指定, Client 數量太多了,放棄。
  5. Linux 啟動兩個 Proftpd ,一個轉碼 for WinXP,一個不轉碼 for Linux lftp,聽不同 port。可行,但好醜。
  6. Linux Proftpd 知道 ftp client 的種類後決定轉碼或不轉碼。

我想採用最佳解 6.,不成功還有 5. 可以用,簡單的測試過 5. 的方法驗證確定可行後,轉攻 6.

過程:
Proftpd Server 有幾個沒有實作的指令 CLNT ACCT LANG,實作 LANG 做語系編碼轉換較佳, 但案子受限不允許於 clinet 額外送出 LANG command。 只好退而求 CLNT 跟 ACCT。 CLNT 本意在送出程式名通知 Server 做區隔。 ACCT 本意對特殊帳號讓 Server 做出特別權限或行為。這兩個都可以拿來利用。 但 ACCT 在 proftpd ldap modules 上有實作,且 ACCT 對往後 code 再利用上我認為較差。 CLNT 命令讓 Server 收到後針對 Clinet 不同而做出不同反應,較符合原意, 但遺憾的是並非所有的 ftp client 都會送出 CLNT 命令, windows 上有幾款 ftp client 會送,測試了但忘了記下來, linux 會送的有 lftp, ncftp。 最後採用修正 proftpd 針對 linux lftp 跟 WinXP ftp 辨別後做轉碼或不轉碼的區分。 於是圖例解法如下。WinXP ftp 端強迫轉碼,linux lftp 則不做轉碼動作。

[4] WinXP ftp[Big5] <--> Linux Proftpd-iconv-CLNT[UTF8] <--> Linux lftp[UTF8]

新增一 proftpd modules ,及 ftp server 指令。在 ftp client 以 FEAT 與詢問 Server Site 要求回傳 211-Features: 211-CLNT 用以觸發 client 送出 CLNT command,以及其他相關特殊命令。

感謝 『使徒提姆』 幫我查 lftp 的 source code, 找出了 FEAT 要求後回傳 211-CLNT,觸發 lftp 送出 CLNT String command。

  • proftpd - iconv 1.3.0-20 deb file -- 將 proftpd iconv 1.2.10 patch port 到 debian etch
  • proftpd - iconv - CLNT 1.3.0-21 deb file -- 針對 CLNT 命令的有無,辨別轉碼或不轉碼的特殊修正
  • Source and patch files
  • May 30, 2008

    如何寫 code 當總統

    有些時候遇到問題或是新任務,在還沒有相對較佳的解法前,我通常不會先動手寫,而是先將問題放著, 然後反覆的想,塗鴉,或是在紙上談兵。往往解答會在聊天,桌巾上,發呆或是在廁所蹦出來。

    某日,開車前往台南的途中,腦袋瓜正想著工作上的難題,邊開車邊發呆邊想問題,不知不覺中嘴巴嘟了起來, 表情很嚴肅。 Roxane 看我擺臭臉,就問我在想什麼或是在煩惱些什麼?被她這麼一問,我反倒不好意思了起來,難得的假日。 回頭想跟她解釋時,又想解釋篇幅很長,說了又不見得能理解,何苦徒增她的困擾呢? 這時候突然幽默附身,隨口說了句逗她開心的玩笑話。

    『我在想如何寫 code 當總統』
    果然此話一出口,她開心的笑了,車上氣氛頓時愉悅起來。 『寫 code 怎麼可能當總統你亂講』--粉拳,嗯嗯嗯。--Roxane 接著說: 『你還不如想想怎樣寫 code 當郭X銘』。於是我們開始 發揮瞎扯的功力,車上一整個歡樂。

    事後想這問題很有趣,寫 code 可以當總統嗎?寫 code 寫到頂會變成什麼呢? Richard Stallman, Bill Gates? 我要的是錢嗎?名嗎?還是我其實我只想當個快樂無知的小米蟲? 我追求的是理想?慾望?成就感?或是安逸快樂呢?我的目標是什麼?我為什麼寫 code? 一堆疑問湧出來?但我沒有答案。當我試圖下個簡單愚頓的結論,『寫 code 是沒有辦法當總統的,就跟 生為公牛是沒有辦法擠出牛奶的,牛就是牛,牛是沒有機會成為總統的』。 我把這個有趣的問題分享給我的半仙好友 smills [1], 他果然馬上迅速的點出我思緒上的錯誤。

    『當雷根沒有當總統前,誰會認為戲子可以當總統』
    『律師,演員可以當總統,為什麼 coder 不能當總統』
    這果然是個樂觀且正面的想法,很好我喜歡話題往這邊發展,當話題終止於兩根香菸後。我知道 單純的寫 code 寫到頂是不可能當總統的,想當總統還必須發展其它技能, 當一種職能因自身天份,時空背景的因素發展到破表邊緣,轉職修煉成就幅度會更大, 也會多給你點技能與籌碼。

    那現在問題來了,我真的想當總統嗎?我不知道,那我想成為什麼呢?嗯這是個好問題?但我確定我 喜歡現在的工作,在還沒有想清楚目的地前,老師說人生目標要遠大,還沒拿定主意前,我的人生 就暫時往這個方向前進吧?把這當成我的目標也滿 kuso 搞笑,嗯..很好我喜歡。

    人生目標就是要遠大啊.....我立志要寫 code 當總統(握拳)

    [1] smills :他以言論辛辣,思緒敏捷,比喻貼切,料敵機先聞名天下。由於他料事如神所以我都尊稱他半仙。

    May 23, 2008

    lpython.py -- one-liner in python

    lpython.py Manual Page
    Source : download

    KaLUG                                   Python Utility Command                          LPYTHON.PY(1)
    
    
    
    NAME
             lpython.py -- one-liner in python.
    
    SYNOPSIS
             [ stdout | ] lpythojn.py 'program-text' [ -p ]
    
    DESCRIPTION
             It converts a one-line script to Python code and executes it. Using \n for newline, [space] for indented.
             It will import os, sys, time, re with default setting for much easier usage.
    
    OPTIONS
             -p print python code
    
    EXAMPLES
             cat /etc/passwd | lpython.py 'for i in stdin:\n s=i.split(":")\n if s[0] == "root":\n  for j in range(len(s)):\n   print s[j]'
             cat /etc/passwd | lpython.py 'for i in stdin:\n s=i.split(":")\n if s[0] == "root":\n  for j in range(len(s)):\n   print s[j]' -p
    >>>>> PYTHON CODE OUTPUT >>>>>>>>>>>>>>>>>>>>>
    from sys import *
    from os import *
    from time import *
    from re import *
    for i in stdin:
            s=i.split(":")
            if s[0] == "root":
                    for j in range(len(s)):
                            print s[j]
    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
             cat /etc/passwd | lpython.py 'for i in stdin:\n s=i.split(":"); print s[0],s[5],s[6],'
             cat /etc/passwd | lpython.py 'for i in stdin:\n s=i.split(":"); print s[0],s[5],s[6],' -p
    
             lpython.py 'for i in range(1,100,5):\n print i'
             lpython.py 'for i in range(1,100,5):\n print i' -p
    
             lpython.py 'for i in range(1,10):\n for j in range(1,10):\n  print "%dx%d=%d\t" % (j,i,i*j),\n print "\n",'
             lpython.py 'for i in range(1,10):\n for j in range(1,10):\n  print "%dx%d=%d\t" % (j,i,i*j),\n print "\n",' -p
    
             uname -a | lpython.py 'print stdin.read().split()'
             uname -a | lpython.py 'list=stdin.read().split();print list[2]+"\n",list'
    
             lpython.py 'a=99;\nfor i in range(50,1000,50):\n print "[%d*%d=%d]" % (a,i,a*i),'
    
    EXAMPLES(2)
             lpython.py 'for i in range(1,10):\n for j in range(1,10):\n  print "%dx%d=%d\t" % (j,i,i*j),\n print "\n",'
    
    lpython.py 'for i in range(1,10):\
     for j in range(1,10):\
      print "%dx%d=%d\t" % (j,i,i*j),\
     print "\n",'
    
    VERSION INFORMATION
             This man page documents lpython.py, version 0.2
    
    AUTHORS
             lloyd at coventive.tv
    
    KaLUG                                   Jul 30 2007                                     LPYTHON.PY(1)
    
    
    

    May 23, 2008

    lpython.py -- python 一行文.

    Shell 與 Unix Tools 透過 pipe line 組合起來威力強大。系統使用與管理上我很喜歡寫 一行文,因為有些時候這種只用一次的 『咒語』 方便好用,也沒有保留的價值。

    但 python 這種利用縮排的程式語言, 一行是個問題。
    我實在很想用 Python 寫一行文,『使徒』救我!!


    最初的想法

    $> python <<EOF
    code....
    code....
    code....
    EOF
    
    $> python <<EOF
    for i in range(0,10):
        print i
    EOF
    
    $> code="
    for i in range(0,10):
        print i
    "
    $> python -c "$code"
    
    
    更多細節 http://timchen119.blogspot.com/2007/02/shell-scriptpython.htm


    進化的版本

  • 利用 "\n" 表示換行
  • 利用 "空白數" 表示縮排階層數
  • 預先引入減少打字數
  • 更多細節 http://timchen119.blogspot.com/2007/07/shell-scriptpython.html


    lpython.py v0.2

  • lpython.py.gz download
  • 安裝: gzip -d lpython.py.gz ; chmod +x lpython.py ; cp lpython.py /usr/local/bin/
  • manual pages: 直接執行 lpython.py 閱讀 manual page.

  • 兩個簡單的範例

    $> cat /etc/passwd | lpython.py 'for i in stdin:\n s=i.split(":"); print s[0],s[5],s[6],'
    $> cat /etc/passwd | lpython.py 'for i in stdin:\n s=i.split(":"); print s[0],s[5],s[6],' -p
    >>>>> PYTHON CODE OUTPUT >>>>>>>>>>>>>>>>>>>>>
    from sys import *
    from os import *
    from time import *
    from re import *
    
    for i in stdin:
            s=i.split(":"); print s[0],s[5],s[6],
    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
    $> lpython.py 'for i in range(1,10):\n for j in range(1,10):\n  print "%dx%d=%d\t" % (j,i,i*j),\n print "\n",'
    $> lpython.py 'for i in range(1,10):\n for j in range(1,10):\n  print "%dx%d=%d\t" % (j,i,i*j),\n print "\n",' -p
    >>>>> PYTHON CODE OUTPUT >>>>>>>>>>>>>>>>>>>>>
    from sys import *
    from os import *
    from time import *
    from re import *
    
    for i in range(1,10):
            for j in range(1,10):
                    print "%dx%d=%d\t" % (j,i,i*j),
            print "\n",
    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    
    更多範例請閱讀 manual page。


    其他類似的想法:

  • pyawk.py http://pyawk.sourceforge.net
  • pyone.py http://www.unixuser.org/~euske/pyone/index.html
  • May 10, 2008

    [tip] rsync over ssh

    [rsync over ssh] <--> [rsync 透過 ssh 與遠端主機同步]

    $> cat rsync_from.sh
    #!/bin/bash
    # 拉
    #
    LOGIN="login_name"
    SITE="127.0.0.1"
    DIRPATH="public_html/"
    cd ~
    rsync -avlR -e ssh ${LOGIN}@${SITE}:${DIRPATH}/* .
    
    $> cat rsync_to.sh
    #!/bin/bash
    # 推
    #
    LOGIN="login_name"
    SITE="127.0.0.1"
    DIRPATH="public_html/"
    cd ~
    rsync -avlR ${DIRPATH}/* -e ssh ${LOGIN}@${SITE}:
    

    May 09, 2008

    [tip] Bash 提示符號如何伸縮自如?

    在 IRC 上有朋友在問,有時因為路徑太長,容易讓過長的 command 需要換行而造成不便。 所以想找找看,有什麼方法 可以將 『Bash 提示符號』動態變長變短,像是 vi editor 一樣,用個指令就可以 將『提示訊息』縮短及伸長。

    這個想法很有趣,不過因為我不是 vi user, 所以我不知道 vi 的這個行為是怎樣的動作, 但我倒是見過不少人的 PS1 會刻意換行,以取得上述想法的平衡點。

           『既想知道完整路徑,又想取得最長 command 空間』

    lloyd@debian:/usr/src/linux-source-2.6.24/drivers
    $ echo \"$PS1\"
    "\u@\h:\w\n$ "
    lloyd@debian:/usr/src/linux-source-2.6.24/drivers
    $
    

    但我越想越覺得這是個有趣及有益身心健康的點子,似乎可以利用一個命令來動態縮短以及伸長『提示符號』, 於是就有了下面的小技巧。可以將 PS1.sh 的內容放在 ~/.bashrc 內,每次登入就可以使用會更加方便。

    $> cat PS1.sh
    PS1 ()
    {
        if [ "$PS1" == '\u@\h \W $ ' ]; then
            PS1='\u@\h \w $ ';
        else
            PS1='\u@\h \W $ ';
        fi
    }
    $> source PS1.sh
    $> PS1
    lloyd@debian:/usr/src/linux-source-2.6.24/drivers $ PS1
    lloyd@debian:drivers $ PS1
    lloyd@debian:/usr/src/linux-source-2.6.24/drivers $ PS1
    lloyd@debian:drivers $