Bu eval
komutu ne yapabilirsin ? Neden faydalıdır? Bash'ta yerleşik bir fonksiyon mu? man
Sayfa yok ..
help eval
kabuğundan "adam" sayfasını almak için
Bu eval
komutu ne yapabilirsin ? Neden faydalıdır? Bash'ta yerleşik bir fonksiyon mu? man
Sayfa yok ..
help eval
kabuğundan "adam" sayfasını almak için
Yanıtlar:
eval
POSIX'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
$foo
değeri ile '10'
ve $x
değer ile 'foo'
.$y
hangi dizeden oluşacağını tanımlayın '$foo'
. Dolar işareti ile kaçılmalıdır '$'
.echo $y
,.'$foo'
eval
. İlk önce $x
dizeye değerlendirecek 'foo'
. Şimdi y=$foo
değ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
eval
yerleş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, eval
bash iç komutudur, bu yüzden bash
man 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 echo
ve VAR=value
iki 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) echo
ve VAR=value
bu 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. eval
Güvenlik sorunlarından kaçınmak için bir komuta yapılan girişler dikkatlice kontrol edilmelidir.
eval
ayrı 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 . bash
Man 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.
eval
güç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 $b
kabuk 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 $b
kabuk 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 eval
veya apropos eval
giriş 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 .
eval
En 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, eval
bir dizgeyi argüman olarak alır ve içindeki kodu değerlendirir / yorumlar. Kabuklarda, eval
birden fazla argüman alabilir, ancak eval
yalnı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 $1
olduğu evil-command; var
, eval
değerlendirilmesi-sona ereceğini evil-command; var=$varvalue
kabuk kodu ve daha sonra bu çalıştırın evil-command
.
Kötülüğü eval
genellikle 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
, awk
ve tabii ki sh
/ bash
/ perl
ve tüm tercümanlar ...
Örnekler (burada kullanılarak uname
olarak evil-command
ve $a
harici 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 $var
kabuk 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.
sed
gibi eval
ve her ikisi için de bu dizginin içeriği kabuk kodu olarak değerlendiriliyor, o sed
kadar tehlikeli eval
, demek istediğim de bu. (şimdiye kadar çalıştırılmayan) sed
iç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. uname
sed
sed '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
. eval
Mevcut 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 command
Bir komutun ne tür olduğunu öğrenmek için kullanın . (type eval
bu davada)