Heim >Backend-Entwicklung >Golang >Wie lese und formatiere ich einen über eine Bash-Pipe empfangenen Textstream?

Wie lese und formatiere ich einen über eine Bash-Pipe empfangenen Textstream?

WBOY
WBOYnach vorne
2024-02-10 23:30:09538Durchsuche

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

Bei unserer täglichen Arbeit müssen wir Textdaten häufig über Befehlszeilentools verarbeiten. In Linux-Systemen ist Bash Pipe (Pipe) ein sehr leistungsfähiges Tool, das die Ausgabe eines Befehls als Eingabe eines anderen Befehls verwenden kann. Aber wie können wir diese Daten effizient lesen und formatieren, wenn wir einen großen Textstrom über eine Pipe empfangen? In diesem Artikel werden Ihnen einige praktische Tipps und Methoden vorgestellt, die Ihnen helfen, über Bash-Pipes empfangene Textströme besser zu verarbeiten. Egal, ob Sie Anfänger oder erfahrener Entwickler sind, dieser Artikel wird Ihnen Inspiration und Hilfe bieten.

Frageninhalt

Derzeit verwende ich Folgendes, um Daten in einem NPM-Skript zu formatieren.

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

Es funktioniert, aber mein Kollege verwendet kein Linux. Also möchte ich while ifs= read -r line;执行 printf '%bn' "$line";在go中完成 implementieren und die Binärdatei in der Pipeline verwenden.

npm run startwin | magical-go-formater

Was ich versucht habe

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)
    }
}

Derzeit schaltet das Programm alle Ausgaben des Textstreams stumm.

Workaround

Sie möchten bufio.scanner zum Lesen von Schwanztypen verwenden. Meiner Meinung nach ist die Überprüfung, die Sie am os.stdin durchgeführt haben, unnötig, aber ymmv.

Siehe diese Antwort für ein Beispiel. ioutil.readall() (现已弃用,只需使用 io.readall() )读取错误/eof,但它不是循环输入 - 这就是您需要 bufio.scanner.scan() Gründe. p>

Außerdem – %b 将转换文本中的任何转义序列 - 例如传递的行中的任何 n werden alle als Zeilenumbrüche gerendert – brauchen Sie das? b/c go hat keinen entsprechenden Formatbezeichner, afaik.

Bearbeiten

Ich denke also, Sie haben den Quellcode der Standardbibliothek von readall() 的方法将会/可能会起作用......最终。我猜您期望的行为与 bufio.scanner 类似 - 接收进程在写入字节时处理字节(这实际上是一个轮询操作 - 请参阅 scan() zugrunde gelegt, um die schmutzigen Details zu sehen) .

Aber bei der instrumentierten Version von readall() 会缓冲读取的所有内容,并且直到最终出现错误或 eof 才会返回。我破解了 readall() (die eine exakte Kopie des Quellcodes der Standardbibliothek ist, mit nur einer kleinen zusätzlichen Instrumentierungsausgabe) können Sie sehen, dass sie liest, während die Bytes geschrieben werden, aber sie wird einfach nicht fertig vor dem Schreibvorgang Es kehrt nicht zurück und produziert vorher keinen Inhalt. An diesem Punkt schließt es das Ende der Pipe (sein offenes Dateihandle) und erzeugt so ein 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
        }
    }
}

Ich habe gerade ein billiges Skript geschrieben, um Eingaben zu generieren, einige lang laufende Dinge zu simulieren und nur in regelmäßigen Abständen zu schreiben. Ich stelle mir vor, wie sich npm in Ihrem Fall verhalten würde:

#!/bin/sh

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

Übrigens finde ich das Lesen des tatsächlichen Standardbibliothekscodes wirklich hilfreich ... oder zumindest in solchen Fällen interessant.

Das obige ist der detaillierte Inhalt vonWie lese und formatiere ich einen über eine Bash-Pipe empfangenen Textstream?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen