Bu evalkomutu ne yapabilirsin ? Neden faydalıdır? Bash'ta yerleşik bir fonksiyon mu? manSayfa yok ..
help evalkabuğundan "adam" sayfasını almak için
Bu evalkomutu ne yapabilirsin ? Neden faydalıdır? Bash'ta yerleşik bir fonksiyon mu? manSayfa yok ..
help evalkabuğundan "adam" sayfasını almak için
Yanıtlar:
evalPOSIX'in bir parçasıdır. Yerleşik bir kabuk olabilen bir arayüz.
"POSIX Programcı El Kitabı" nda açıklanmıştır: http://www.unix.com/man-page/posix/1posix/eval/
eval - construct command by concatenating arguments
Bir argüman alacak ve bunun için kabuk tarafından yürütülecek bir komut oluşturacaktır. Manpage örneği budur:
1) foo=10 x=foo
2) y='$'$x
3) echo $y
4) $foo
5) eval y='$'$x
6) echo $y
7) 10
$foodeğeri ile '10've $xdeğer ile 'foo'.$yhangi dizeden oluşacağını tanımlayın '$foo'. Dolar işareti ile kaçılmalıdır '$'.echo $y,.'$foo'eval. İlk önce $xdizeye değerlendirecek 'foo'. Şimdi y=$foodeğerlendirilecek olan ifademiz var y=10.echo $yşimdi değerdir '10'.Bu, birçok dilde yaygın bir fonksiyondur, örneğin Perl ve JavaScript. Daha fazla örnek için perldoc eval'e bir göz atın: http://perldoc.perl.org/functions/eval.html
evalyerleşik bir işlevdir, bir işlev değildir. Uygulamada, yerleşikler, bir dil tanımına sahip olmayan, ancak tam olarak değil (denilen bir işlevi tanımlamaya yetecek kadar bükülürseniz görünür hale gelir) görünmeyen işlevler gibi davranırlar eval.
Evet, evalbash iç komutudur, bu yüzden bashman sayfasında açıklanmıştır .
eval [arg ...]
The args are read and concatenated together into a single com-
mand. This command is then read and executed by the shell, and
its exit status is returned as the value of eval. If there are
no args, or only null arguments, eval returns 0.
Genellikle bir Komut Değiştirme ile birlikte kullanılır . Açık olmadan eval, kabuk çalışır yürütmek için değil, bir komut ikamesi sonucunu değerlendirmek onu.
Bir eşdeğerini kodlamak istediğinizi söyleyin VAR=value; echo $VAR. Kabuğun, aşağıdakilerin yazılarını işleme biçimindeki farkı not edin echo VAR=value:
andcoz@...:~> $( echo VAR=value )
bash: VAR=value: command not found
andcoz@...:~> echo $VAR
<empty line>
Kabuk yürütmeye çalışırsa echove VAR=valueiki ayrı komutlar olarak. İkinci dize hakkında bir hata atar. Atama etkisiz kalır.
andcoz@...:~> eval $( echo VAR=value )
andcoz@...:~> echo $VAR
value
Kabuk iki dizgiyi birleştirir (birleştirir) echove VAR=valuebu tek birimi uygun kurallara göre ayrıştırır ve yürütür.Son fakat en az değil, evalçok tehlikeli bir komut olabilir. evalGüvenlik sorunlarından kaçınmak için bir komuta yapılan girişler dikkatlice kontrol edilmelidir.
evalayrı bir dış komut değil, yalnızca kabuk ( bash) tarafından bilinen ve içten bir komut anlamına gelen bir kabuk yerleşik olduğu için bir man sayfasına sahip değildir . bashMan sayfasının ilgili kısmı şöyle diyor:
eval [arg ...]
The args are read and concatenated together into a single command.
This command is then read and executed by the shell, and its exit
status is returned as the value of eval. If there are no args, or only
null arguments, eval returns 0
Ek olarak, eğer çıktı ise help eval:
eval: eval [arg ...]
Execute arguments as a shell command.
Combine ARGs into a single string, use the result as input to the shell,
and execute the resulting commands.
Exit Status:
Returns exit status of command or success if command is null.
evalgüçlü bir komuttur ve eğer onu kullanmak istiyorsanız, beraberinde gelebilecek olası güvenlik risklerinden kaçınmak için çok dikkatli olmalısınız .
Eval deyimi, kabuğa eval'ün argümanlarını komut olarak almalarını ve komut satırından geçirmelerini söyler. Aşağıdaki gibi bir durumda faydalıdır:
Komut dosyanızda bir değişkenin içine bir komut tanımlıyorsanız ve daha sonra bu komutu kullanmak istiyorsanız, eval kullanmalısınız:
/home/user1 > a="ls | more"
/home/user1 > $a
bash: command not found: ls | more
/home/user1 > # Above command didn't work as ls tried to list file with name pipe (|) and more. But these files are not there
/home/user1 > eval $a
file.txt
mailids
remote_cmd.sh
sample.txt
tmp
/home/user1 >
ls | more. Başka bir deyişle: Tek komut adı, boşluklar ve çizgi sembolünü içeren dokuz karakterden oluşuyordu. .
eval, genellikle yerleşik olarak uygulanan bir kabuk komutudur.
POSIX'te "eval" girişindeki " 2.14. Özel Dahili Yardımcı Programlar" ın bir parçası olarak listelenmiştir .
Yerleşik anlamı:
"Yerleşik" terimi, kabuğun yardımcı programı doğrudan çalıştırabileceğini ve onu aramaya gerek duymadığını belirtir.
Basit bir ifadeyle: bir giriş satırının iki kez ayrıştırılmasını sağlar .
Kabuk, bir çizgiyi "işlemden geçirmek" için izleyen adımlar dizisine sahiptir. Sen olabilir Bu resim bakmak ve eval gider tek çizgi, arka solda, 1. adıma olduğunun farkında. Gönderen POSIX açıklaması :
2.1 Kabuk Giriş
- Kabuk girişini okur ....
- Kabuk girişi belirteçlere böler: kelimeler ve operatörler
- Kabuk, girişi basit ve bileşik komutlara ayrıştırır.
- Kabuk çeşitli açılımlar yapar (ayrı olarak) ...
- Kabuk, yeniden yönlendirme gerçekleştirir ve yeniden yönlendirme işleçlerini ve onların işleçlerini parametre listesinden kaldırır.
- Kabuk bir işlevi, yerleşik, çalıştırılabilir bir dosyayı veya komut dosyasını çalıştırır ...
- Kabuk isteğe bağlı olarak komutun çıkış durumunu tamamlamasını ve toplamasını bekler.
6. adımda yerleşik bir işlem gerçekleştirilecektir.
6. adımda, değerlendirme işlenen hattın 1. adıma geri gönderilmesine neden olur
. Uygulama sırasının geri döndüğü tek koşul budur.
Bu yüzden şunu söylüyorum: eval ile bir giriş satırı iki kez ayrıştırıldı .
Ve anlamak için en önemli etki. Bir çizginin ilk kez gösterilmesinin bir sonucu, yukarıda gösterilen yedi kabuk basamağına maruz kalmasıdır . 4. adımda (açılımlar) , en son Alıntı Kaldırma olan tüm açılımları gerçekleştirmek için bir dizi adım da vardır :
Alıntı kaldırma her zaman en son yapılmalıdır.
Dolayısıyla, her zaman, kaldırılmış bir alıntı düzeyi vardır.
Bu ilk etkinin sonucu olarak, hattın ilave / farklı kısımları kabuk ayrıştırmaya ve diğer tüm adımlara maruz kalmaktadır.
Bu, dolaylı açılımların yürütülmesine izin verir:
a=b b=c ; eval echo \$$a ### shall produce "c"
Neden? Çünkü ilk döngüde, ilk $alıntı yapılır.
Bu nedenle, kabuk tarafından genişlemeler için göz ardı edilir.
A $ismi ile bir sonraki "b" üretmek için genişletildi.
Ardından, ilk alıntı yapılmadan bir seviye alıntı yapılır $.
İlk döngünün sonu.
O zaman, ikinci döngüde dizgenin $bkabuk tarafından okunmasıdır.
Sonra "c" ye genişledi ve
argüman olarak verildi echo.
İlk döngüde hangi değerlendirmenin üreteceğini "görmek" için (yeniden değerlendirilmek üzere), echo kullanın. Veya argümanları açıkça gösteren herhangi bir komut / script / program:
$ a=b b=c
$ eval echo \$$a;
c
Ne olduğunu "görmek" için, eval ile eco'yu değiştirin:
$ echo echo \$$a
echo $b
Bir satırın tüm "kısımlarını" aşağıdakilerle göstermek de mümkündür:
$ printf '<%s> ' echo \$$a
<echo> <$b>
Bu örnekte, yalnızca bir yankı ve bir değişkendir, ancak daha karmaşık durumların değerlendirilmesinde yardımcı olduğunu unutmayın.
Şunu söylemek gerekir: Yukarıdaki kodda bir hata var, görebiliyor musunuz?
Kolay: bazı alıntılar eksik.
Nasıl? sorabilirsin. Basit, değişkenleri değiştirelim (kodu değil):
$ a=b b="hi jk"
$ eval echo \$$a
hi jk
Kayıp boşlukları gördün mü?
Bunun nedeni, içindeki değerin $bkabuk tarafından bölünmüş olmasıdır.
Bu sizi ikna etmiyorsa, şunu deneyin:
$ a=b b="hi * jk"
$ eval echo \$$a ### warning this will expand to the list
### of all files in the present directory.
Eksik alıntılar. Doğru çalışması için (iç "$a"ve dış \"tırnak işaretleri ekleyin ).
Bunu dene (tamamen güvenli):
$ a=b b="hi * jk"
$ eval echo \" \$"$a" \"
hi * jk
Onun için adam sayfası yok.
Hayır, bunun için bağımsız bir adam sayfası yok. El ile arama man -f evalveya apropos evalgiriş bile göstermiyor.
İçeride bulunur man bash. Herhangi bir yerleşik olarak.
"SHELL BUILTIN KOMUTLARI" ve ardından "eval" için arama yapın.
Yardım almanın daha kolay bir yolu şudur: Kısaca help eval, yerleşiklerin yardımlarını görmek için bunu yapabilirsiniz .
Çünkü metni dinamik olarak koda bağlar.
Başka bir deyişle: argümanlarının listesini (ve / veya bu argümanların genişlemesini) yürütülen bir satıra dönüştürür. Herhangi bir nedenle, bir saldırgan tarafından bir argüman ayarlandıysa, saldırgan kodunu yürüteceksiniz.
Ya da daha da basit, eval ile bir veya birkaç argümanın değerini kimin tanımladığını söyleyeceksiniz:
Hadi, buraya oturun ve herhangi bir komut satırı yazın, bunu güçlerimle yürüteceğim.
Bu tehlikeli mi? Bu herkes için açık olmalı.
Eval için emniyet kuralı olmalıdır:
Sadece hangi değişkenlere eval yürütmek Eğer bu değer verdik.
Daha fazla ayrıntıyı burada okuyun .
evalEn yorumlanır dillerin (bir özelliğidir TCL, python, ruby...), sadece kabukları. Kodu dinamik olarak değerlendirmek için kullanılır.
Kabuklarda, kabuk yerleşik komutu olarak uygulanır.
Temel olarak, evalbir dizgeyi argüman olarak alır ve içindeki kodu değerlendirir / yorumlar. Kabuklarda, evalbirden fazla argüman alabilir, ancak evalyalnızca değerlendirilecek dizeyi oluşturmak için bunları birleştirir.
Çok güçlü çünkü kodu dinamik olarak oluşturabilir ve çalıştırabilirsiniz, C gibi derlenmiş dillerde yapamayacağınız bir şey
Sevmek:
varname=$1 varvalue=$2
eval "$varname=\$varvalue" # evaluate a string like "foo=$varvalue"
# which in Bourne-like shell language
# is a variable assignment.
Ancak eval, kabuk kodu olarak yorumlanmasının nedenlerinden dolayı , aktarılanların dinamik (harici olarak sağlanan) bölümlerini dezenfekte etmek önemlidir .
Örneğin, yukarıdaki halinde $1olduğu evil-command; var, evaldeğerlendirilmesi-sona ereceğini evil-command; var=$varvaluekabuk kodu ve daha sonra bu çalıştırın evil-command.
Kötülüğü evalgenellikle abartılı.
Tamam, tehlikeli, ama en azından tehlikeli olduğunu biliyoruz.
(Kabuk bağlı olarak) gibi temizlenmiş değil, diğer komutların bir çok bağımsız değişkenler içinde kabuk kodunu değerlendirecek [aka test, export, printf, GNU sed, awkve tabii ki sh/ bash/ perlve tüm tercümanlar ...
Örnekler (burada kullanılarak unameolarak evil-commandve $aharici olarak sağlıksız verileri sağlanır):
$ a='$(uname>&2)' sh -c 'eval "echo $a"'
Linux
$ a='x[0$(uname>&2)]' mksh -c 'export "$a=$b"'
Linux
$ a='x[0$(uname>&2)]' ksh93 -c 'printf "%d\n" "$a"'
Linux
0
$ a='x[0$(uname>&2)]' ksh93 -c '[ "$a" -gt 0 ]'
Linux
$ a=$'bar/g;e uname>&2\n;s//'; echo foo | sed "s/foo/$a/g"
Linux
bar
$ a='";system("uname");"'; awk "BEGIN{print \"$a\"}"
Linux
$ a=';uname'; sh -c "echo $a"
Linux
Bunlar sed, export... komutları daha tehlikeli olarak kabul edilebilirdi , çünkü eval "$var"içeriğin $varkabuk kodu olarak değerlendirilmesine neden olacağı açık olsa da, sed "s/foo/$var/"ya export "$var=value"da ya da ile açık değildir [ "$var" -gt 0 ]. Dangerosity aynıdır, ancak diğer komutlarda da gizlidir.
sedgibi evalve her ikisi için de bu dizginin içeriği kabuk kodu olarak değerlendiriliyor, o sedkadar tehlikeli eval, demek istediğim de bu. (şimdiye kadar çalıştırılmayan) sediçeren bir dize geçiriliyor ve uname komutu çalıştırılarak sonlandırılıyor. Eval için gibi. Olarak şunları yapmanız Temizlenmemiş verilerinin geçirilmesi değiliz biz burada konuştuğumuz şey değil. unamesedsed 's/foo/$a/g'sed
Bu örnek biraz ışık tutabilir:
#!/bin/bash
VAR1=25
VAR2='$VAR1'
VAR3='$VAR2'
echo "$VAR3"
eval echo "$VAR3"
eval eval echo "$VAR3"
Yukarıdaki betiğin çıktısı:
$VAR2
$VAR1
25
eval. evalMevcut cevaplarda kapsanmayan , işlevselliğinin bazı temel, kritik yönlerinin olduğuna inanıyor musunuz ? Eğer öyleyse, o zaman açıklayın ve açıklamanızı göstermek için örneği kullanın. Lütfen yorumlara cevap vermeyin; cevabınızı daha net ve daha eksiksiz hale getirmek için düzenleyin .
type commandBir komutun ne tür olduğunu öğrenmek için kullanın . (type evalbu davada)