Frage von GunnarPetite, 45

Linux shell (bash) read Befehl funktioniert nicht?

grep suchwort datei | awk -F "," '{ print $7 } | read variable

Oben stehende Befehlsverkettung funktioniert bis einschließlich zum awk Kommando. Es werden mehrere Werte ausgegeben.

Aber egal, ob ich read eine oder mehrere Variable zuweise, diese bleiben immer leer. Eigentlich liest read doch von stdin? Wo liegt mein Fehler?

Hilfreichste Antwort - ausgezeichnet vom Fragesteller
von guenterhalt, Community-Experte für Linux, 31

ich verstehe nicht was du hier mit read anfangen willst.
read ist kein Linux-Befehl, read ist ein eingebautes Kommando der bash.

Aa kann ich leider nicht sagen, ob das auf Pipes ( | ) reagiert.

Offensichtlich willst du  nur die Ausgabe von grep ... |awk ---- in einer Variablen speichern.

Das geht doch ganz einfach mit

variable=`grep suchwort datei| awk ..... `

(möglicherweise auch noch export davor, wenn sie in nachfolgenden Shells benutzt werden soll)

Kommentar von GunnarPetite ,

Hab es auch schon mit den Backticks versucht, Resultat ist leider dasselbe. Noch eine Idee?

Und was soll es mir sagen, dass read kein Linux- sondern ein bash-Kommando ist? Macht es die Benutzung in meinem script weniger legitim?

Kommentar von guenterhalt ,

Linux-Kommandos sind Binaries, also ausführbare Programme. Programmierer solcher Programme halten sich da schon an gewisse Standards u.a. auch bei den Umlenkungen wie der Pipe.

Bei in solche Programme eingebaute Befehle, muss das nicht funktionieren:

So würde

 echo /etc | cd 

auch nicht das Gleiche wie

cd /etc

bewirken. Auch cd ist ein bash-Kommando.

Bei der Wahl der "einfachen Hochkomma" hat wohl kaum einer keine Probleme mit den dreien  ' ,  ` ,  ´

variable=`grep zeichenkette datei-name | awk -F "," '{ print $7 }' `

funktioniert das bei mir.

Das erste ` ist Shift "Taste neben <--"
Das vor {  ist Shift#
Das nach } wieder Shift#
das letzte dann wieder  Shift "Taste neben <--"

 

Kommentar von GunnarPetite ,

Vielen Dank für die ausführlichen Erklärungen. 

Was die Zeichen angeht, hatte ich schon die richtigen, ich arbeite selbst oft mit Backticks, um Ausgaben von Befehlen in Variable zu speichern. 

Allerdings hat auch das hier nicht geholfen. Muss noch ein paar Experimente machen, ich glaube, ich bin der Sache auf der Spur. 

Danke erstmal für Dein Engagement, melde mich nochmal, wenn ich die Lösung finden sollte.

Kommentar von Linuxhase ,

Das erste ` ist Shift "Taste neben <--"
Das vor {  ist Shift#
Das nach } wieder Shift#
das letzte dann wieder  Shift "Taste neben <--"

Weswegen ich schon lange die moderne und vor allem besser lesbare Variante benutze:

variable=$(grep zeichenkette datei-name | awk -F "," '{ print $7 }' )

Da "sieht ein Blinder mit Krückstock" dass das was in den runden Klammern ist ausgeführt wird.

Linuxhase

Kommentar von GunnarPetite ,

Super! Das wollte ich nämlich auch noch googlen, ob das dasselbe ist. Vielen Dank ! Alles in allem gibt´s dafür 15 Punkte (in der Schule war das eine eins!)

Kommentar von GunnarPetite ,

Im übrigen habe ich das Problem bisher nicht über Variable lösen können.

Es läuft jetzt über Ausleitung der Strings in eine Datei und das Script iteriert dann fröhlich über die Strings in der Datei. Auf dem Wege funktioniert es. Das hinterlässt natürlich noch Fragezeichen.

Antwort
von Linuxhase, 3

Hallo nochmal

Im übrigen habe ich das Problem bisher nicht über Variable lösen können.

Wenn Dein:

grep suchwort datei | awk -F "," '{ print $7 } | read variable

nicht funktioniert, wie wäre es so?:

variable=$(grep suchwort datei | awk -F "," '{ print $7 })

Dann sollte es doch klappen.

Es läuft jetzt über Ausleitung der Strings in eine Datei

Kann man so machen. Ob das sinnvoll oder schneller oder besser ist hängt konkret davon ab was Du tun möchtest und wie Du es umsetzt.

  • Leg doch mal das Beispiel beiseite und zeig das richtige Konstrukt mit dem Du arbeitest.

Linuxhase

Kommentar von GunnarPetite ,

Das hatte ich leider auch schon vergeblich versucht. Habe zur Zeit keinen Zugriff auf das Script, aber das hatte weder mit  $() noch mit `..` geklappt. War ganz seltsam. Auf der Kommandozeile ging es, nur im Script nicht.

Kommentar von Linuxhase ,

@GunnarPetite

Habe zur Zeit keinen Zugriff auf das Script

Tja, keine Arme, keine Beine ;-)

Linuxhase

Antwort
von GWBln, 9

Ich blicke nicht ganz durch, was du genau machen willst, aber ich kann dir die Grundstruktur erläutern:

Befehl mit mehrzeiliger Ausgabe |
(
# für alle Zeilen der Ausgabe
while read Var1 Var2
do
    # läuft in sub-shell! verarbeite $Var1 $Var2
 # ---> Vorsicht mit einem weiteren read!
done
)

wichtig ist das pipe symbol nach dem Befehl! ... die Ausgabe wird in die geklammerten Anweisungen 'gesendet'

Am Ende sind die Variablen Var1 und Var2 nicht mehr definiert!

oder (Interpretation eines Verzeichnisses, hier im /proc/ - Baum), die Ausgabe landet auch hier im geklammerten Block:

(
   while read
   do
       # läuft in sub-shell!
   done
) < /proc/scsi/scsi  # implizite Schleife (loop)
Antwort
von Linuxhase, 11

Hallo

grep suchwort datei | awk -F "," '{ print $7 } | read variable

Wie wäre es mit:

read var <<< $(grep suchwort datei | awk -F "," '{ print $7 })

oder Du erklärst mal was das Konstrukt machen soll, denn es gibt bestimmt noch elegantere Wege.

Wo liegt mein Fehler?

Die Variable hat den Namen variable, aber es wird nichts über die Pipe hineingeschrieben weil read ein Shell-Kommando (build in) ist und kein zusätzliches Programm.

Linuxhase

Kommentar von GunnarPetite ,

Ganz kann ich da nicht zustimmen: 

ls -l | grep * | while read variable; do echo variable ; done

schreibt auch über read in eine Variable. Und dass es an read nicht liegt, habe ich bereits bewiesen: Eine Zuweisung an eine Variable aus einem Befehl mittels Backticks hat ebenso wenig geholfen. 

Das Interessante ist, dass awk durchaus etwas ausgibt, aber sich der Output eben nicht in eine Variable speichern lässt. 

Was ich machen möchte, kann ich dir sagen, wenn du mit dem Sleuthkit vertraut bist. Letzendlich möchte ich aus einer Timeline die inodes auslesen, was über awk bereits funktioniert. 

Ein eleganterer Weg löst allerdings nicht das Problem, denn mich interessiert ganz speziell, WARUM dieses Problem auftritt. 

Kommentar von Linuxhase ,

@GunanrPetite

ls -l | grep * | while read variable; do echo variable ; done

Das ist Quatsch, dabei wird überhaupt nichts in die Variablen geschrieben sondern lediglich das Wort variable ausgegeben.

Es wird hierbei das Kommando ls ausgeführt und grep gibt die gewünschte Ausgabe dann aus (mit Fehlermeldungen, weil es keine Verzeichnisse durchsucht.

Wenn Du das Kommando ohne grep verwendest bekommst Du öfter variable ausgegeben als mit grep, denn dann wird auch für jede Fehlermeldung die while-Schleife ausgeführt. Es ist also nur eine Zählung.

Eine Zuweisung an eine Variable aus einem Befehl mittels Backticks hat ebenso wenig geholfen.

Bei mir funktioniert mein Kommando auch mit den backticks.

Das Interessante ist, dass awk durchaus etwas ausgibt, aber sich der Output eben nicht in eine Variable speichern lässt.

Nicht über die Pipe.

Letzendlich möchte ich aus einer Timeline die inodes auslesen, was über awk bereits funktioniert.

Wie genau lautet denn das Kommando?

denn mich interessiert ganz speziell, WARUM dieses Problem auftritt.

Wurde doch bereits von guenterhalt geschrieben, weil es eine bulit-in ist.

Linuxhase

Antwort
von leseratten1, 15

read liest Dateien byteweise oder von der Tastatur-Eingabe.

Wenn du die Ausgabe eines Befehls in eine Variable packen willst, geht das z.B. so:

HOSTNAME=`/bin/hostname`
echo $HOSTNAME


Kommentar von GunnarPetite ,

Nicht ganz richtig. read liest nach Bedarf auch bis EOL

read variable 

liest deine Eingabe, bis du Enter drückst und speichert in der Variablen. Das Problem scheint ein anderes zu sein, denn deine Variante mit den Backticks hat auch nicht funktioniert.

awk gibt eine mehrzeilige Ausgabe aus , diese Zeilen bekomme ich aber nicht in eine Variable gespeichert. Was ich seltsam finde... 

Kommentar von leseratten1 ,

Ja, das meinte ich, mit "Tastatur-Eingabe".

In interaktiven Skripten nutze ich read auch, aber eben nicht so, wie in deinem Beispiel ;-)

Welches Linux, Shell und Version verwendest du denn?

Kommentar von Linuxhase ,

@leseratten1

Bei mir arbeitet die:

GNU bash, Version 4.3.46(1)

Linuxhase

Kommentar von Linuxhase ,

@GunanrPetite

awk gibt eine mehrzeilige Ausgabe aus , diese Zeilen bekomme ich aber nicht in eine Variable gespeichert. Was ich seltsam finde...

Wen Du mehrere Zeilen schreibst, etwa so:

read VARIABLE <<< $(echo "Hallo
Welt")

gibt folgendes aus:

echo $VARIABLE
Hallo Welt

Es hebt die Zeilenumbrüche auf und schreibt alles in eine Zeile ;-)

Linuxhase

Keine passende Antwort gefunden?

Fragen Sie die Community

Weitere Fragen mit Antworten