Standart sed bir kabuk çağıramaz ( sadece gömülü olmayan Linux'u önemsiyorsanız GNU sed bunu yapmak için bir uzantıya sahiptir ), bu yüzden sed dışındaki işlemlerden bazılarını yapmanız gerekir. Birkaç çözüm var; hepsi dikkatli alıntılar gerektirir.
Değerlerin nasıl genişletilmesini istediğiniz açık değildir. Örneğin, bir çizgi
foo hello; echo $(true) 3
çıktı aşağıdakilerden hangisi olmalıdır?
k=<foo> value=<hello; echo 3>
k=<foo> value=<hello; echo 3>
k=<foo> value=<hello; echo 3>
k=<foo> value=<foo hello
3>
Aşağıda çeşitli olasılıkları tartışacağım.
saf kabuk
Kabuğu giriş satır satır okuyabilir ve işleyebilirsiniz. Bu en basit çözüm ve aynı zamanda kısa dosyalar için en hızlı çözümdür. “ echo \2
” Gereksiniminize en yakın şey bu :
while read -r keyword value; do
echo "k=<$keyword> v=<$(eval echo "$value")>"
done
read -r keyword value
kümeler $keyword
ilk boşluk ile ayrılmış hattın kelime ve $value
satır eksi arka boşluk geri kalanına.
Değişken referanslarını genişletmek istiyor ancak komut yerine başka komutlar uygulamak istemiyorsanız, burada bir belgenin$value
içine koyun . Gerçekten aradığın şey olduğundan şüpheleniyorum.
while read -r keyword value; do
echo "k=<$keyword> v=<$(cat <<EOF
$value
EOF
)>"
done
sed bir mermi içine borulu
Girişi kabuk betiğine dönüştürebilir ve değerlendirebilirsiniz. Sed o kadar da kolay değil. “ echo \2
” Gereksiniminizi yerine getirmek (anahtar kelimedeki tek tırnak işaretlerinden kaçmamız gerektiğini unutmayın):
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
Burada bir belgeyle devam edersek, yine de anahtar kelimeden kaçmamız gerekir (ancak farklı).
{
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
Çok fazla veriniz varsa bu en hızlı yöntemdir: her satır için ayrı bir işlem başlatmaz.
awk
Sed ile yaptığımız aynı teknikler awk ile çalışır. Ortaya çıkan program çok daha okunaklıdır. “ echo \2
” İle devam etmek :
awk '
1 {
kw = $1;
sub(/^ *[^ ]+ +/, "");
gsub(/\047/, "\047\\\047\047", $1);
print "echo \047k=<" kw ">\047 v=\\<" $0 "\\>";
}' | sh
Burada bir belgeyi kullanma:
awk '
NR==1 { print "cat <<EOF" }
1 {
kw = $1;
sub(/^ *[^ ]+ +/, "");
gsub(/\\\$`/, "\\&", $1);
print "k=<" kw "> v=<" $0 ">";
}
END { print "EOF" }
' | sh