首頁 > 後端開發 > Golang > 主體

如何讀取和格式化透過 bash 管道接收的文字流?

WBOY
發布: 2024-02-10 23:30:09
轉載
521 人瀏覽過

如何读取和格式化通过 bash 管道接收的文本流?

在我們的日常工作中,經常需要透過命令列工具來處理文字資料。而在Linux系統中,bash管道(pipe)是一個非常強大的工具,可以將一個指令的輸出作為另一個指令的輸入。但是,當我們透過管道接收到一大段文字流時,如何有效地讀取和格式化這些資料呢?本文將為大家介紹一些實用的技巧和方法,幫助你更好地處理透過bash管道接收的文字流。無論你是初學者還是有一定經驗的開發者,本文都將為你帶來一些啟發和幫助。

問題內容

目前,我正在使用以下內容來格式化 npm 腳本中的資料。

npm run startwin | while ifs= read -r line; do printf '%b\n' "$line"; done | less
登入後複製

它可以工作,但我的同事不使用 linux。所以,我想實作 while ifs= read -r line;執行 printf '%b\n' "$line";在go中完成,並在管道中使用二進位檔案。

npm run startwin | magical-go-formater
登入後複製

我嘗試過的

package main

import (
    "fmt"
    "io/ioutil"
    "os"
    "strings"
)

func main() {
  fi, _ := os.Stdin.Stat() // get the FileInfo struct

  if (fi.Mode() & os.ModeCharDevice) == 0 {

    bytes, _ := ioutil.ReadAll(os.Stdin)
    str := string(bytes)
    arr := strings.Fields(str)

    for _, v := range arr {
      fmt.Println(v)
    }
}

登入後複製

目前,程式會靜默文字流的所有輸出。

解決方法

您想要使用 bufio.scanner 進行尾部類型讀取。恕我直言,您在 os.stdin 上進行的檢查是不必要的,但是 ymmv。

請參閱此答案以了解範例。 ioutil.readall() (現已棄用,只需使用io.readall() )讀取錯誤/eof,但它不是循環輸入- 這就是您需要bufio.scanner.scan() 的原因。

此外 - %b 將轉換文字中的任何轉義序列 - 例如傳遞的行中的任何 \n 都會呈現為換行符號 - 您需要嗎? b/c go 沒有等效的格式說明符,afaik。

編輯

所以我認為,您基於 readall() 的方法將會/可能會起作用......最終。我猜您期望的行為與bufio.scanner 類似- 接收進程在寫入位元組時處理位元組(這實際上是一個輪詢操作- 請參閱scan() 的標準庫原始碼以查看骯髒的細節) .

但是 readall() 會緩衝讀取的所有內容,並且直到最終出現錯誤或 eof 才會回傳。我破解了readall() 的檢測版本(這是標準庫原始碼的精確副本,只有一點點額外的檢測輸出),您可以看到它在寫入位元組時正在讀取,但它只是沒有在寫入過程完成之前不會返回並產生內容,此時它會關閉管道的末端(其打開的文件句柄),從而生成eof:

package main

import (
    "fmt"
    "io"
    "os"
    "time"
)

func main() {

    // os.stdin.setreaddeadline(time.now().add(2 * time.second))

    b, err := readall(os.stdin)
    if err != nil {
        fmt.println("error: ", err.error())
    }

    str := string(b)
    fmt.println(str)
}

func readall(r io.reader) ([]byte, error) {
    b := make([]byte, 0, 512)
    i := 0
    for {
        if len(b) == cap(b) {
            // add more capacity (let append pick how much).
            b = append(b, 0)[:len(b)]
        }
        n, err := r.read(b[len(b):cap(b)])

        //fmt.fprintf(os.stderr, "read %d - received: \n%s\n", i, string(b[len(b):cap(b)]))
        fmt.fprintf(os.stderr, "%s read %d - received %d bytes\n", time.now(), i, n)
        i++

        b = b[:len(b)+n]
        if err != nil {
            if err == io.eof {
                fmt.fprintln(os.stderr, "received eof")
                err = nil
            }
            return b, err
        }
    }
}
登入後複製

我剛剛編寫了一個廉價的腳本來產生輸入,模擬一些長時間運行的東西並且僅定期編寫,我想像 npm 在你的情況下的表現如何:

#!/bin/sh

for x in 1 2 3 4 5 6 7 8 9 10
do
  cat ./main.go
  sleep 10
done
登入後複製

順便說一句,我發現閱讀實際的標準庫程式碼確實很有幫助......或者至少在這樣的情況下很有趣。

以上是如何讀取和格式化透過 bash 管道接收的文字流?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:stackoverflow.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板