iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 22
1

前言

我們在昨天已經想好一套實作 Redirect Stdin 的方法,大致上可以分成這幾個步驟:

  1. 嘗試開啟 data 檔案
  2. 若檔案 不存在 就噴錯,程式到此結束
  3. 若檔案存在,就把指令的 Stdin 設為 data 檔案
  4. 執行指令

實作

func executeInput(input string) error {
    // ...

    args := parseArgs(input)

    // ...

    // 先設好預設的 inputStream
    // 預設是從終端機進行讀取
    inputStream := os.Stdin

    // 如果 args 有大於兩個元素,譬如說 ["python", "<", "data"]
    // 而且倒數第二個(len(args)-2)是 "<"
    // 那就需要重新導向 Stdin
    if len(args) > 2 && args[len(args)-2] == "<" {
        // 檔案名稱是最後一個參數
        // 這邊的 filename = "data"
        filename := args[len(args)-1]
        
        // 1. 用昨天講到的 Open 嘗試開啟檔案
        file, err := os.Open(filename)
        
        // 2. 如果發生錯誤的話(檔案不存在)就回傳錯誤
        if err != nil {
            return err
        }

        // 3. 檔案存在的話就把 inputStream 設為 file 檔案
        inputStream = file
        
        // 4. 執行 python 指令
        // 因為結尾的 < data 不是 python 的參數
        // 所以把最後兩個參數刪掉,只保留前面的 python
        // 此時的 args = ["python"]
        args = args[:len(args)-2]
    }

    cmd := exec.Command(args[0], args[1:]...)

    // 把 Stdin 來源設為 inputStream
    // 如果沒有經過 Redirect,那 inputStream 就是終端機
    // 如果有經過 Redirect,則 inputStream 會是那個檔案
    cmd.Stdin = inputStream
    
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr

    err := cmd.Run()
    return err
}

Demo

把資料餵給 python

若檔案不存在

小結

View commit on Github

因為時間不多所以今天只實作了 Redirect Stdin,但其實 Redirect Stdout 也是差不多的做法,大致上就是 檔案開起來、資料寫進去,有興趣可以自己試試看XD

今天應該是寫最多扣的一天,跟之前一樣有問題歡迎在下方提問,沒問題的話明天就要進入 Signal 的部分了,這部分比較難,各位看倌要有點心理準備哦~


上一篇
Day21-Redirect Stdin(一)
下一篇
Day23-Signal 訊號(一)
系列文
Gosh!原來用 Go 寫一個 Unix Shell 這麼簡單30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言