Ich habe eine Textdatei mit folgendem Format:
keyword value
keyword value
...
Wobei das Schlüsselwort ein einzelnes Wort und der Wert alles andere bis zum Zeilenende ist. Ich möchte die Datei aus einem Shell-Skript so lesen, dass die Werte (aber nicht die Schlüsselwörter) eine Shell-Erweiterung erfahren.
Mit sed ist es einfach, die Schlüsselwörter und Wertteile abzugleichen
input='
keyword value value
keyword "value value"
keyword `uname`
'
echo "$input"|sed -e 's/^\([^[:space:]]*\)[[:space:]]\(.*\)$/k=<\1> v=<\2>/'
was produziert
k=<keyword> v=<value value>
k=<keyword> v=<"value value">
k=<keyword> v=<`uname`>
Dann stellt sich die Frage, wie ich einen Shell-Befehl in den Ersatzteil des sed-Ausdrucks einbetten kann. In diesem Fall möchte ich den Ersatz haben \1 `echo \2`
.
Antworten:
Standard sed kann keine Shell aufrufen ( GNU sed hat eine Erweiterung , wenn Sie sich nur für nicht eingebettetes Linux interessieren), daher müssen Sie einen Teil der Verarbeitung außerhalb von sed ausführen. Es gibt verschiedene Lösungen. Alle erfordern sorgfältiges Zitieren.
Es ist nicht genau klar, wie die Werte erweitert werden sollen. Zum Beispiel, wenn eine Linie ist
Welche der folgenden Angaben sollte die Ausgabe sein?
Ich werde im Folgenden einige Möglichkeiten diskutieren.
reine Schale
Sie können die Shell veranlassen, die Eingabe zeilenweise zu lesen und zu verarbeiten. Dies ist die einfachste und auch die schnellste Lösung für kurze Dateien. Dies kommt Ihrer Anforderung "
echo \2
" am nächsten :read -r keyword value
Setzt$keyword
auf das erste durch Leerzeichen getrennte Wort der Zeile und$value
auf den Rest der Zeile abzüglich des nachgestellten Leerzeichens.Wenn Sie Variablenverweise erweitern möchten, aber keine Befehle außerhalb von Befehlsersetzungen ausführen möchten, fügen Sie sie
$value
in ein Here-Dokument ein . Ich vermute, dass Sie genau danach gesucht haben.sed in eine Muschel gepumpt
Sie können die Eingabe in ein Shell-Skript umwandeln und auswerten. Sed ist der Aufgabe gewachsen, auch wenn es nicht so einfach ist. Entsprechend Ihrer "
echo \2
" Anforderung (beachten Sie, dass das Keyword in einfachen Anführungszeichen stehen muss):Wenn Sie ein Here-Dokument verwenden, müssen Sie das Schlüsselwort immer noch umgehen (aber anders).
Dies ist die schnellste Methode, wenn Sie viele Daten haben: Es wird nicht für jede Zeile ein separater Prozess gestartet.
awk
Die gleichen Techniken, die wir bei sed angewendet haben, arbeiten mit awk. Das resultierende Programm ist deutlich lesbarer. Gehen mit "
echo \2
":Verwenden eines Here-Dokuments:
quelle
Mit GNU können
sed
Sie den folgenden Befehl verwenden:Welche Ausgänge:
mit Ihren Eingabedaten.
Erläuterung:
Der Befehl sed unterdrückt die reguläre Ausgabe mit der
-n
Option.-r
wird übergeben, um erweiterte reguläre Ausdrücke zu verwenden, wodurch wir einige Sonderzeichen im Muster vermeiden, dies ist jedoch nicht erforderlich.Mit dem
s
Befehl wird die Eingabezeile in den Befehl übertragen:Das Schlüsselwort wird nicht in Anführungszeichen gesetzt. Ich übergebe die Option
e
- die GNU-spezifisch ist - an dens
Befehl, der sed anweist, das Ergebnis der Ersetzung als Shell-Befehl auszuführen und die Ergebnisse in den Musterpuffer zu lesen (auch mehrere Zeilen). Mit der Optionp
nach (!)e
Machtsed
den Musterpuffer Druck , nachdem der Befehl ausgeführt wurde.quelle
-n
undp
Optionen dh verzichtensed -r 's/([^ ]+) (.*)/echo "\1" \2\n/e' input
. Aber danke dafür! Ich wusste nicht über diee
Option.e
Option geht (eingeführt von GNU). Ist das immer nochsed
? :)Sie könnten diesen Ansatz ausprobieren:
(Wenn ich deine Absicht richtig verstanden habe). Das heißt, fügen Sie "process" am Anfang jeder nicht leeren Zeile ein, um daraus ein Skript wie das folgende zu machen:
zu evaluieren (
eval
) wobei process eine Funktion ist, die die erwartete Nachricht ausgibt.quelle
Wenn eine nicht gesetzte Lösung akzeptabel ist, erledigt dieses PERL-Snippet die Aufgabe:
quelle
NUR KISS SHORT PURE SED
ich werde dies tun
und es funktioniert.
quelle