it-swarm.com.de

Wie lese ich mehrzeilige Eingaben von stdin in variable und wie drucke ich eine in Shell aus (sh, bash)?

Was ich tun möchte, ist das Folgende:

  1. mehrzeilige Eingabe von stdin in Variable A einlesen
  2. verschiedene Operationen für A ausführen
  3. pipe A ohne Begrenzungssymbole zu verlieren (\n, \r, \t, etc) auf einen anderen Befehl

Das aktuelle Problem ist, dass ich es nicht mit dem Befehl read einlesen kann, da es bei newline nicht mehr liest.

Ich kann stdin mit cat so lesen:

my_var=`cat /dev/stdin`

, aber dann weiß ich nicht, wie ich es ausdrucken soll. Damit sind die Zeilenumbrüche, Tabulatoren und anderen Begrenzer noch vorhanden.

Mein Beispielskript sieht folgendermaßen aus:

#!/usr/local/bin/bash

A=`cat /dev/stdin`

if [ ${#A} -eq 0 ]; then
        exit 0
else
        cat ${A} | /usr/local/sbin/nextcommand
fi
55
kakas

Das funktioniert bei mir:

myvar=`cat`

echo "$myvar"

Die Anführungszeichen um $myvar sind wichtig.

63
Tanktalus

In Bash gibt es einen alternativen Weg; man bash Erwähnt:

Die Befehlsersetzung $(cat file) kann durch die entsprechende, aber schnellere $(< file) ersetzt werden.

$ myVar=$(</dev/stdin)
hello
this is test
$ echo "$myVar"
hello
this is test
24
Ingo Karkat

tee erledigt den Job

#!/bin/bash
myVar=$(tee)
9

Ja, es funktioniert auch bei mir. Vielen Dank.

myvar=`cat`

ist das gleiche wie

myvar=`cat /dev/stdin`

Nun ja. Auf der Manpage bash:

Das Einschließen von Zeichen in doppelte Anführungszeichen behält den Literalwert aller Zeichen in den Anführungszeichen bei, mit Ausnahme von $, `,\und, wenn die Verlaufserweiterung aktiviert ist,!. Die Zeichen $ und `behalten in Anführungszeichen ihre besondere Bedeutung.

7
kakas

Wenn Sie daran interessiert sind, nachgestellte Zeilenumbrüche am Ende der Ausgabe beizubehalten, verwenden Sie Folgendes:

myVar=$(cat; echo x)
myVar=${myVar%x}
printf %s "$myVar"

Dies verwendet den Trick von hier .

4
Ingo Karkat

[Aktualisiert]

Diese Zuweisung bleibt auf unbestimmte Zeit hängen, wenn sich nichts in der Pipe befindet ...

var="$(< /dev/stdin)"

Wir können dies jedoch verhindern, indem wir für das erste Zeichen eine Zeitüberschreitung read festlegen. Wenn das Zeitlimit überschritten wird, ist der Rückkehrcode größer als 128 und die STDIN-Pipe (a.k.a /dev/stdin) Ist leer.

Ansonsten bekommen wir den Rest von STDIN per ...

  • setzen Sie IFS für den Befehl read auf NULL
  • escape mit -r ausschalten
  • das Trennzeichen von read wird mit -d '' entfernt.
  • und schließlich, das an den Charakter anzuhängen, den wir anfangs bekamen

Somit...

__=""
_stdin=""

read -N1 -t1 __  && {
  (( $? <= 128 ))  && {
    IFS= read -rd '' _stdin
    _stdin="$__$_stdin"
  }
}

Bei dieser Technik wird die Verwendung von var="$(command ...)" Command Substitution vermieden, bei der abschließende Zeilenumbrüche konstruktionsbedingt immer entfernt werden.

Wenn die Befehlsersetzung bevorzugt wird, können wir zur Beibehaltung nachfolgender Zeilenumbrüche ein oder mehrere Trennzeichen an die Ausgabe innerhalb der Funktion $() anhängen und sie dann außerhalb entfernen.

Zum Beispiel (beachte $(parens) im ersten Befehl und ${braces} Im zweiten) ...

_stdin="$(awk '{print}; END {print "|||"}' /dev/stdin)"
_stdin="${_stdin%|||}"
3
DocSalvager