
Ich habe eine einfache Bash-Funktion, die zwei Zahlen dividiert:
echo "750/12.5" | bc
Ich möchte die Ausgabe von nehmen bc
und /24
das Ergebnis an eine andere Instanz von anhängen und weiterleiten bc
.
Etwas wie:
echo "750/12.5" | bc | echo $1 + "/24" | bc
Wo $1
ist das weitergeleitete Ergebnis?
echo "750/12.5/24" | bc
PS: Mir ist klar, dass ich meine Frage eher auf das Anhängen von Text an ein Pipe-Ergebnis beziehen könnte .
Antwort1
Dies habe ich erreicht, indem ich sed
das Zeilenende verwendet und ersetzt habe:
echo "my text" | sed 's/$/ more text/'
Kehrt zurück:
my text more text
Ihr Beispiel:
echo "750/12.5" | bc | sed 's/$/\/24/' | bc
Antwort2
Alternativer Ansatz:
TL;DR: Verwenden Sie es cat
zum Verketten mit stdin ( -
) als Argument. Beachten Sie, dass Ihre verketteten Streams durch Zeilenumbrüche getrennt werden. Entfernen Sie es, wenn dies unerwünscht ist.
Leider ist dieser Ansatz für Ihren speziellen Anwendungsfall etwas umständlich, da bc
er fehlschlägt, wenn sich in der Mitte des Ausdrucks ein Zeilenumbruch befindet:
$ echo "750/12.5" | bc | cat - <(echo "/24") | bc
60
(standard_in) 2: parse error
Sie können dies umgehen, indem Sie die neue Zeile aus dem ursprünglichen bc
Ergebnis löschen:
$ echo "750/12.5" | bc | tr -d '\n' | cat - <(echo "/24") | bc
2
Ich bin jedoch auf diese Frage gestoßen, als ich "bash append to pipe" gegoogelt habe, und in meinem Fall habe ich tatsächlichTunmöchten, dass zwischen den Verkettungen eine neue Zeile steht. Für diejenigen, die aus demselben Grund hier sind, verwenden Sie | cat - <(...)
:
$ echo foo | cat - <(echo bar)
foo
bar
$ echo foo | cat - <(echo bar) | sort | cat - <(echo last_line)
bar
foo
last_line
$ echo foo | cat - <(echo bar) | sort | cat <(echo header) - <(echo last_line)
header
bar
foo
last_line
Antwort3
Bei der einfachsten Option wird dies an den Pipe-Stream angehängt:
$ echo "750/12.5" | { bc; echo "/24"; }
60
/24
Dies führt jedoch zu einem unerwarteten Zeilenumbruch. Um dies zu vermeiden, müssen Sie entweder tr verwenden:
$ echo "750/12.5" | { bc | tr -d '\n' ; echo "/24"; }
60/24
Oder, angesichts der Tatsache, dass eine Befehlserweiterung nachfolgende Zeilenumbrüche entfernt:
$ printf '%s' $( echo "750/12.5" | bc ); echo "/24"
60/24
Die korrekte Vorgehensweise sollte jedoch wahrscheinlich folgendermaßen aussehen:
$ echo "$(echo "750/12.5" | bc )/24"
60/24
Zur Verwendung in bc könnte es wie folgt geschrieben werden:
$ bc <<<"$(bc <<<"750/12.5")/24"
2
Um eine angemessene Genauigkeit bei Gleitkommazahlen zu erreichen, sollte es etwa so aussehen:
$ bc <<<"scale=10;$(bc <<<"scale=5;750/12.5")/24"
2.5000000000
Beachten Sie, dass zwei Skalen erforderlich sind, da es zwei Instanzen von bc gibt.
Natürlich benötigt eine Instanz von bc nur eine Skala:
$ bc <<<"scale=5;750/12.5/24"
Tatsächlich sollten Sie es in Bezug auf eine Zeichenfolge betrachten:
$ a=$(echo "750/12.5") # capture first string.
$ echo "$a/24" | bc # extend the string
2
Der oben genannte Kommentar zum Maßstab ist hier weiterhin gültig.
Antwort4
Sie können Folgendes verwenden, awk
um alles in die Pipe einzufügen/anzuhängen:
$ date | awk 'BEGIN{print "prefix line"} {print} END{print "suffix line"}'
prefix line
Mo 21. Aug 15:24:30 CEST 2023
suffix line
Wo
date
- ist Ihr Eingabekanal (hier beispielsweise das aktuelle Datum)BEGIN{print "prefix line"}
- dieser Block fügt die Ausgabe vor dem Hauptblock ein{print}
- druckt den Inhalt der Eingabepipe; hier könnte man bei Bedarf einige Verarbeitungen durchführenEND{print "suffix line"}
- dies hängt die Ausgabe nach main an
Um dasselbe in einer einzelnen Zeile zu tun, verwenden Sie einfach printf
:
$ date | awk 'BEGIN{printf("prefix line >> ")} {printf($0)} END{printf(" << suffix line")}'
prefix line >> Mo 21. Aug 15:32:08 CEST 2023 << suffix line/upload/sc505enb/tmp>
$ echo "750/12.5" | bc | awk '{printf($0)} END{printf("/24\n")}'
60/24