Standardowy sed nie może wywoływać powłoki ( GNU sed ma do tego rozszerzenie , jeśli zależy ci tylko na niewbudowanym Linuksie), więc będziesz musiał wykonać część przetwarzania poza sed. Istnieje kilka rozwiązań; wszystkie wymagają starannego cytowania.
Nie jest jasne, w jaki sposób chcesz rozszerzyć wartości. Na przykład, jeśli linia to
foo hello; echo $(true) 3
który z poniższych wyników powinien być?
k=<foo> value=<hello; echo 3>
k=<foo> value=<hello; echo 3>
k=<foo> value=<hello; echo 3>
k=<foo> value=<foo hello
3>
Omówię kilka możliwości poniżej.
czysta skorupa
Możesz uzyskać powłokę do odczytu linii wejściowej po linii i przetworzenia jej. Jest to najprostsze rozwiązanie, a także najszybsze w przypadku krótkich plików. To jest najbliższe wymaganiu „ echo \2
”:
while read -r keyword value; do
echo "k=<$keyword> v=<$(eval echo "$value")>"
done
read -r keyword value
ustawia $keyword
na pierwsze słowo linii rozdzielane spacjami, a $value
na resztę linii minus końcowe spacje.
Jeśli chcesz rozwinąć odwołania do zmiennych, ale nie wykonujesz poleceń poza podstawieniami poleceń, umieść $value
w tym dokumencie dokument . Podejrzewam, że tego właśnie tak naprawdę szukałeś.
while read -r keyword value; do
echo "k=<$keyword> v=<$(cat <<EOF
$value
EOF
)>"
done
sed wpięty do muszli
Możesz przekształcić dane wejściowe w skrypt powłoki i to ocenić. Sed spełnia swoje zadanie, choć nie jest to takie proste. Zgodnie z wymaganiem „ echo \2
” (pamiętaj, że musimy unikać pojedynczych cudzysłowów w słowie kluczowym):
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
Przechodząc do dokumentu tutaj, nadal musimy uciec od słowa kluczowego (ale inaczej).
{
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
Jest to najszybsza metoda, jeśli masz dużo danych: nie rozpoczyna osobnego procesu dla każdej linii.
awk
Te same techniki, których używaliśmy przy sed, działają z awk. Powstały program jest znacznie bardziej czytelny. Idąc z „ echo \2
”:
awk '
1 {
kw = $1;
sub(/^ *[^ ]+ +/, "");
gsub(/\047/, "\047\\\047\047", $1);
print "echo \047k=<" kw ">\047 v=\\<" $0 "\\>";
}' | sh
Korzystanie z dokumentu tutaj:
awk '
NR==1 { print "cat <<EOF" }
1 {
kw = $1;
sub(/^ *[^ ]+ +/, "");
gsub(/\\\$`/, "\\&", $1);
print "k=<" kw "> v=<" $0 ">";
}
END { print "EOF" }
' | sh