Sed standar tidak dapat memanggil shell ( GNU sed memiliki ekstensi untuk melakukannya , jika Anda hanya peduli pada Linux yang tidak tertanam), jadi Anda harus melakukan beberapa pemrosesan di luar sed. Ada beberapa solusi; semua membutuhkan mengutip dengan cermat.
Tidak jelas bagaimana Anda ingin nilai diperluas. Misalnya, jika sebuah garis
foo hello; echo $(true) 3
mana dari berikut ini yang harus menjadi output?
k=<foo> value=<hello; echo 3>
k=<foo> value=<hello; echo 3>
k=<foo> value=<hello; echo 3>
k=<foo> value=<foo hello
3>
Saya akan membahas beberapa kemungkinan di bawah ini.
cangkang murni
Anda bisa mendapatkan shell untuk membaca input baris demi baris dan memprosesnya. Ini adalah solusi paling sederhana, dan juga yang tercepat untuk file pendek. Ini adalah hal yang paling dekat dengan kebutuhan Anda " echo \2
":
while read -r keyword value; do
echo "k=<$keyword> v=<$(eval echo "$value")>"
done
read -r keyword value
set $keyword
ke kata pertama yang dibatasi spasi spasi, dan $value
ke seluruh baris dikurangi spasi spasi.
Jika Anda ingin memperluas referensi variabel, tetapi tidak menjalankan perintah di luar pergantian perintah, masukkan ke $value
dalam dokumen di sini . Saya menduga ini adalah apa yang sebenarnya Anda cari.
while read -r keyword value; do
echo "k=<$keyword> v=<$(cat <<EOF
$value
EOF
)>"
done
sed disalurkan ke shell
Anda dapat mengubah input menjadi skrip shell dan mengevaluasinya. Sed sampai dengan tugas, meskipun itu tidak mudah. Mengikuti echo \2
persyaratan " " Anda (perhatikan bahwa kami perlu menghindari tanda kutip tunggal dalam kata kunci):
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
Pergi dengan dokumen di sini, kita masih perlu melarikan diri kata kunci (tetapi berbeda).
{
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
Ini adalah metode tercepat jika Anda memiliki banyak data: itu tidak memulai proses terpisah untuk setiap baris.
awk
Teknik yang sama kami gunakan dengan sed work dengan awk. Program yang dihasilkan jauh lebih mudah dibaca. Going with " echo \2
":
awk '
1 {
kw = $1;
sub(/^ *[^ ]+ +/, "");
gsub(/\047/, "\047\\\047\047", $1);
print "echo \047k=<" kw ">\047 v=\\<" $0 "\\>";
}' | sh
Menggunakan dokumen di sini:
awk '
NR==1 { print "cat <<EOF" }
1 {
kw = $1;
sub(/^ *[^ ]+ +/, "");
gsub(/\\\$`/, "\\&", $1);
print "k=<" kw "> v=<" $0 ">";
}
END { print "EOF" }
' | sh