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
foo hello; echo $(true) 3
Welche der folgenden Angaben sollte die Ausgabe sein?
k=<foo> value=<hello; echo 3>
k=<foo> value=<hello; echo 3>
k=<foo> value=<hello; echo 3>
k=<foo> value=<foo hello
3>
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 :
while read -r keyword value; do
echo "k=<$keyword> v=<$(eval echo "$value")>"
done
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.
while read -r keyword value; do
echo "k=<$keyword> v=<$(cat <<EOF
$value
EOF
)>"
done
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):
sed -e 's/^ *//' -e 'h' \
-e 's/[^ ]* *//' -e 'x' \
-e 's/ .*//' -e "s/'/'\\\\''/g" -e "s/^/echo 'k=</" \
-e 'G' -e "s/\n/>' v=\\</" -e 's/$/\\>/' | sh
Wenn Sie ein Here-Dokument verwenden, müssen Sie das Schlüsselwort immer noch umgehen (aber anders).
{
echo 'cat <<EOF'
sed -e 's/^ */k=</' -e 'h' \
-e 's/[^ ]* *//' -e 'x' -e 's/ .*//' -e 's/[\$`]/\\&/g' \
-e 'G' -e "s/\n/> v=</" -e 's/$/>/'
echo 'EOF'
} | sh
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
":
awk '
1 {
kw = $1;
sub(/^ *[^ ]+ +/, "");
gsub(/\047/, "\047\\\047\047", $1);
print "echo \047k=<" kw ">\047 v=\\<" $0 "\\>";
}' | sh
Verwenden eines Here-Dokuments:
awk '
NR==1 { print "cat <<EOF" }
1 {
kw = $1;
sub(/^ *[^ ]+ +/, "");
gsub(/\\\$`/, "\\&", $1);
print "k=<" kw "> v=<" $0 ">";
}
END { print "EOF" }
' | sh