ubuntuusers.de

sed: Zeile als Variable in bash

Status: Ungelöst | Ubuntu-Version: Kein Ubuntu
Antworten |

zmsvsq

Anmeldungsdatum:
4. Februar 2013

Beiträge: 37

Hallo,

danke super! @Kinch: wie funktioniert 'read line' in deiner Schleife?

@all: Ich habe noch ein kleines sed-Problem (für das sich, denke ich ein neuer Thread kaum lohnt).

Ich habe eine Datei, die in etwa so aussehen könnte:

>>> cat ~/.Test
echo $TERM
var=blabla; echo $var
vim ~/.Test

ich möchte nun einzelne Zeilen aus dieser Datei mit sed auslesen und das Kommando, aus der Zeile ausfüren.

Mein Ansatz ist folgender (er funktioniert Problemlos, wenn es nichts zu expandieren gibt) - die Fehlermeldungen gleich mitgepostet:

>>> $(sed -n "1p" ~/.Test)
$TERM

>>> $(sed -n "2p" ~/.Test)
bash: var=blabla;: Kommando nicht gefunden. 

>>> $(sed -n "3p" ~/.Test)
vim öffnet eine leere Datei mit dem Hinweis: "~/.Test" [Neues VERZEICHNIS]

alle Fälle lassen sich lösen mit:

>>> sed -n "1p" ~/.Test | bash
xterm 
>>> sed -n "2p" ~/.Test | bash
blabla
>>> sed -n "3p" ~/.Test | bash
Vim: Warnung: Die Eingabe kommt nicht von einem Terminal

Die Lösung ist aber nicht gerade schön und führt insbesondere im letzten Fall immer noch zu einer Warnung. Gibt es eine elegante Lösung? Muss ich irgendwie anders quoten? Der Inhalt der Datei selbst sollte im Idealfall nicht bearbeitet werden.

Moderiert von Antiqua:

Dieses Thema wurde von hier abgetrennt. Bitte erstelle für ein neues Problem ein neues Thema. Für einen besseren Titelvorschlag soll sich der Ersteller bitte via PM bei mir melden.

NoKurth

Avatar von NoKurth

Anmeldungsdatum:
18. August 2006

Beiträge: 430

Hallo zmsvsq.

zmsvsq schrieb:

[...]
ich möchte nun einzelne Zeilen aus dieser Datei mit sed auslesen und das Kommando, aus der Zeile ausfüren.
[...]

Setze einfach ein "eval" davor, also z.B. so:

1
eval $(sed -n "1p" ~/.Test)

Gruß
Norman

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Worum geht es denn tatsächlich ? - willst Du die Datei teilweise ausführen oder worauf willst Du hinaus ? (warum also das sed ?)

Normalerweise würde man dafür den source (oder Punkt)- Befehl benutzen, aber der führt die ganze Datei aus.
Aber vielleicht lässt sich da in Verbindung mit einer Process Substitution was machen ? - sowas in der Art:

track@lucid:~$ . <( echo 'echo abc
echo 234
echo 1x' |  sed -n 2p )
234 

Allerdings ist sowas ggf. ein Sicherheitsrisiko, weil damit beliebiger Code eingeschleust werden kann. (Das gilt für eval umso mehr !)

LG,

track

zmsvsq

(Themenstarter)

Anmeldungsdatum:
4. Februar 2013

Beiträge: 37

Hallo,

was Norman vorschlägt ist genau das was ich suche.

@Track: Wo ist das Problem, wenn ich eval nutze, mit eval $(sed -n "2p" ~/.Test) ist die Eingabe dann doch abgeschlossen?

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Die Datei ~/.Test kommt ja irgendwo her. Und wenn dort jemand heimlich bösartigen Code einfügt, dann kannst Du das Skript mit den Rechten zunageln wie Du willst, der wird trotzdem ausgeführt ! - Das ist der Punkt.

Deshalb sind solche hinten herum ausführbaren Daten-Dateien immer so 'ne Sache, und vom Sicherheitsaspekt her absolut nicht gern gesehen.

track

Kinch

Anmeldungsdatum:
6. Oktober 2007

Beiträge: 1261

zmsvsq:

danke super! @Kinch: wie funktioniert 'read line' in deiner Schleife?

'read' ist ein Kommando das eine Zeile von stdin ließt und den Wert einer Variable, hier mit dem Namen 'line', zuordnet.

while read line
do
...
done

ließt solange von stdin, bis ein EOF gelesen wird und 'read' ein 'false' zurück gibt.

zmsvsq

(Themenstarter)

Anmeldungsdatum:
4. Februar 2013

Beiträge: 37

Hallo,

danke für eure Antworten.

@Kinch: Danke für die Erläuterung; jetzt habe ich Deine Schleife verstanden.

@track: Um es für mein Verständnis nocheinmal zusammenzufassen. Das Problem ist nicht das Kommando 'eval' als solches, sondern das Auslesen eines Kommandos aus einer Datei. Selbst, wenn das ausführende Shellskript nur root ausführen dürfte; könnte, wenn die Datei ~/.Test nicht entspreched "gesichert" ist, jeder Hinz und Kuntz etwas in die Datei einfügen, was dann Schaden anrichten würde, weil die Kommandos aus der Datei ohne Nachfrage ausgeführt werden, sobald das Shellskript ausgeführt wrid. Ist das so richtig?

@all: gibt es einen Weg, die Ausgabe des Kommandos: 'sed -n "1p" ~/.Test' nicht direkt auszugeben, sondern editierbar hinter einem neuen Prompt, so daß es also nicht direkt ausgeführt wird, wie bei 'eval $(sed -n "1p" ~/.Test)', sondern das Kommando hinter einen neuen Prompt geschrieben wird, man es editieren kann und es erst durch Bestätigung mit Enter ausgeführt wird.

 
>>> Kommando <Zeile i> # Kommando list die die i'te Zeile aus ~/.Test            [ENTER]
>>> hier steht die i'te Zeile aus der Datei ~/Test (das ist der aktuelle Prompt) [ENTER]
Kommando aus Zeile i wird ausgeführt. 

NoKurth

Avatar von NoKurth

Anmeldungsdatum:
18. August 2006

Beiträge: 430

zmsvsq schrieb:

[...]
@all: gibt es einen Weg, die Ausgabe des Kommandos: 'sed -n "1p" ~/.Test' nicht direkt auszugeben, sondern editierbar hinter einem neuen Prompt, so daß es also nicht direkt ausgeführt wird,
[...]

Ja! ☺ Ich habe das ganze mal in ein kleines Skript gepackt.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash

# Eingabedatei
INPUTDATEI=~/.Test
# Anzahl der Zeilen der Eingabedatei
AnzahlZeilen=$(wc -l ${INPUTDATEI} | awk ' // { print $1; } ')

# jede Zeile der Eingabedatei abarbeiten
for LaufZeile in $(seq 1 ${AnzahlZeilen})
 do
  # Zeile aus Datei einlesen
  Zeile=$(sed -n "${LaufZeile}p" ${INPUTDATEI})
  # Abfrage beim Benutzer
  #  -i ... Voreinstellung - also das, was gelesen wurde
  #  -p ... Prompt - Text vor editierbarem Text
  #  -e ... Zielvariable
  read -i "${Zeile}" -p "Befehl: " -e Befehl
  # Kontrollausgabe
  echo ">eval ${Befehl}<"
  # ${Befehl} ausfuehren - Kommentarzeichen am Anfang der naechsten Zeile entfernen
  #eval ${Befehl}
done

Gruß
Norman

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

zmsvsq schrieb:

@track: Um es für mein Verständnis noch einmal zusammenzufassen. Das Problem ist nicht das Kommando 'eval' als solches, sondern das Auslesen eines Kommandos aus einer Datei. Selbst, wenn das ausführende Shellskript nur root ausführen dürfte; könnte, wenn die Datei ~/.Test nicht entspreched "gesichert" ist, jeder Hinz und Kuntz etwas in die Datei einfügen, was dann Schaden anrichten würde, weil die Kommandos aus der Datei ohne Nachfrage ausgeführt werden, sobald das Shellskript ausgeführt wrid. Ist das so richtig?

Ja, genau das ist das das Risiko. So wie Du das einsetzt, nehmen sich source und eval tatsächlich nichts, weil sie beide im Endeffekt das selbe machen.

@all: gibt es einen Weg, die Ausgabe des Kommandos: 'sed -n "1p" ~/.Test' nicht direkt auszugeben, sondern editierbar hinter einem neuen Prompt, so daß es also nicht direkt ausgeführt wird, wie bei 'eval $(sed -n "1p" ~/.Test)', sondern das Kommando hinter einen neuen Prompt geschrieben wird, man es editieren kann und es erst durch Bestätigung mit Enter ausgeführt wird.

Das ist auch nicht wirklich elegant. Besser wäre, wenn Du die Eingabe aus der Datei mit sed (oder wie auch immer) so scharf filterst, dass wirklich nur die korrekten Sachen durchkommen. (... falls der Sicherheitsaspekt hier wirklich so wichtig ist !)

track

zmsvsq

(Themenstarter)

Anmeldungsdatum:
4. Februar 2013

Beiträge: 37

Hallo,

danke für eure Antworten.

@NoKurth: Das ist genau was ich suche. Kann man das Kommando auch für die zsh adaptieren?

NoKurth

Avatar von NoKurth

Anmeldungsdatum:
18. August 2006

Beiträge: 430

Hallo zmsvsq.

zmsvsq schrieb:

[...] Kann man das Kommando auch für die zsh adaptieren?

Keine Ahnung. Ich arbeite in meinen Skripten immer mit der Bash - mit der zsh habe ich keinerlei Erfahrung... Hast du schon mal

1
man zsh

probiert? Vielleicht findest du dort, wie du das für dich anpassen kannst.

Viele Grüße
Norman

Antworten |