2010-05-24 16 views
10

aşağıdaki daha tembel değerlendirme yapmanın daha zarif bir yolu var mı . Bash'de bunu yapmanın daha iyi bir yolu var mı?Tembel Değerlendirme Bash

+0

merak ediyorum yapmak istediğiniz neden şöyle Sonra kullanmak Bu ya da aslında ne elde etmeye çalışıyorsun. Bazen 'eval', gitmek için doğru ya da tek yoldur, ancak 'declare' ve 'printf' özelliklerinin de yararlı olabileceği özel özellikler de vardır. Ve neyin peşinde olduğunuzu başarmanın başka yolları da olabilir. –

+0

Yapılandırılabilir olmak istediğim bir bash komut dosyası var. Kullanıcının bir "desen" belirtme yeteneğine sahip olmasını istiyorum. Daha sonra, kalıptaki bazı değişkenler, betik tarafından çalıştırılan etkinliklerle (SQL sorguları, SOAP çağrıları ve diğer şirket içi yardımcı programlar) değiştirilecek ve başka bir komut satırı programına geçirilecektir. Ben Bash için biraz yeni ve bu yaklaşım hakkında bir şey sadece yanlış geliyor. Daha fazla bilgi için teşekkürler. – User1

cevap

4

Değerler güvenilmeyen kaynaklardan gelmediği sürece güvenlik riski yoktur. Bazı alternatifler örneğin, gettext gelen komutu envsubst kullanabilirsiniz olsa da, vardır: hepsi

expand_pattern() { 
    pattern="$x and $y" 
} 

:

$ pattern='$x and $y' 
$ x=1 y=2 envsubst <<< $pattern 
1 and 2 
+0

Sanırım güvenlik olayları bu dava için biraz paranoyak. Ekstra teklifleri beğeniyorum. – User1

0

Haklısınız, eval bu durumda bir güvenlik riski taşıyor. Burada olası bir yaklaşımdır: "dolunayda ve gökyüzü açık olduğunda kurtadam aktiftir"

pattern='The $a is $b when the $z is $x $c $g.' # simulated input from user (use "read") 
unset results 
for word in $pattern 
do 
    case $word in 
     \$a) 
      results+=($(some_command)) # add output of some_command to array (output is "werewolf" 
      ;; 
     \$b) 
      results+=($(echo "active")) 
      ;; 
     \$c) 
      results+=($(echo "and")) 
      ;; 
     \$g) 
      results+=($(echo "the sky is clear")) 
      ;; 
     \$x) 
      results+=($(echo "full")) 
      ;; 
     \$z) 
      results+=($(echo "moon")) 
      ;; 
      *) 
      do_something # count the non-vars, do a no-op, twiddle thumbs 
      # perhaps even sanitize %placeholders, terminal control characters, other unwanted stuff that the user might try to slip in 
      ;; 
    esac 
done 
pattern=${pattern//\$[abcgxz]/%s} # replace the vars with printf string placeholders 
printf "$pattern\n" "${results[@]}" # output the values of the vars using the pattern 
printf -v sentence "$pattern\n" "${results[@]}" # put it into a variable called "sentence" instead of actually printing it 

çıkışı olacaktır Aynı program, eğer desen '$ x $ z $ c $ g ise, $ a $ b olmalıdır. sonra çıkış "Dolunay çıktı ve gökyüzü açıktı, bu yüzden kurtadam aktif olmalı."

+1

Yanıt, sorunun örneğiyle eşleşiyor. Ancak, temel dizge değiştirmelerden daha karmaşık bir şey için çok kullanışlı görünmüyor. Bu yaklaşımı takip etmeye çalışırsam, Bash'de bir Bash yorumcusu yazmalıyım. – ceving

+0

Cevabım, komut dosyasının bir kullanıcının güvenilir olmayan girişinden yalıtılmasını sağlayan bir yöntemdir. Sorgunun cevabına göre soruna ekli OP'nin yorumuna dayanıyor. –

2

biri güvenli olasılık fonksiyonunu kullanmaktır. (Bunlar ana kapsam dokunulmaz değildir böylece)

x=1 y=1 
expand_pattern 
echo "$pattern" 

Hatta ortam değişkenleri olarak x ve y kullanabilirsiniz::

x=1 y=1 expand_pattern 
echo "$pattern" 
+1

Daha önce burada olmasaydı yazmam gereken cevap budur. (Daha sonra tekrar eklendikten sonra, bu soruyu ön sayfaya geri döndürerek cevaplandırdım). :) –