बाश में "eval" कमांड क्या है?


176

आप evalकमांड के साथ क्या कर सकते हैं ? क्यों उपयोगी है? क्या यह किसी प्रकार का बना-बनाया कार्य है जो बैश में है? इसका कोई manपृष्ठ नहीं है ।।


28
कमांडtype command किस प्रकार की है यह जानने के लिए उपयोग करें । ( ths मामले में)type eval
rozcietrzewiacz


3
help evalअपने खोल से "आदमी" पृष्ठ पाने के लिए
m-ric

eval एक बैश-बिलिन है और इसे bash के मैन पेज में प्रलेखित किया जाता है। तो बस "मैन बैश" टाइप करें और eval के लिए उपयुक्त अनुभाग खोजें। यह अन्य बैश-बिल्डरों के लिए भी लागू होता है।
डिर्क थेनहूसर

जवाबों:


132

evalPOSIX का हिस्सा है। इसका एक इंटरफ़ेस जो एक शेल निर्मित हो सकता है।

इसका वर्णन "पॉसिक्स प्रोग्रामर मैनुअल" में दिया गया है: http://www.unix.com/man-page/posix/1posix/eval/

eval - construct command by concatenating arguments

यह एक तर्क लेगा और इसकी एक कमांड का निर्माण करेगा, जिसे शेल द्वारा निष्पादित किया जाएगा। यह मैनपेज का उदाहरण है:

1) foo=10 x=foo
2) y='$'$x
3) echo $y
4) $foo
5) eval y='$'$x
6) echo $y
7) 10
  1. पहली पंक्ति में आपके द्वारा निर्धारित $fooमूल्य के साथ '10'और $xमूल्य के साथ 'foo'
  2. अब परिभाषित करें $y, जिसमें तार शामिल हैं '$foo'। डॉलर के चिन्ह के साथ बच जाना चाहिए '$'
  3. परिणाम देखने के लिए, echo $y
  4. परिणाम स्ट्रिंग होगा '$foo'
  5. अब हम असाइनमेंट को दोहराते हैं eval। यह पहले $xस्ट्रिंग का मूल्यांकन करेगा 'foo'। अब हमारे पास वह वक्तव्य है y=$fooजिसका मूल्यांकन किया जाएगा y=10
  6. का परिणाम echo $yअब मूल्य है '10'

यह कई भाषाओं में एक सामान्य कार्य है, जैसे पर्ल और जावास्क्रिप्ट। अधिक उदाहरणों के लिए perldoc eval पर एक नज़र डालें: http://perldoc.perl.org/functions/eval.html


4
शेल शब्दावली में, evalएक अंतर्निहित, एक फ़ंक्शन है। व्यवहार में, बिल्ट-इन बहुत सारे कार्यों की तरह व्यवहार करता है, जिसमें इन-लैंग्वेज की परिभाषा नहीं होती है, लेकिन काफी (जैसा कि यदि आप एक फ़ंक्शन को परिभाषित करने के लिए पर्याप्त रूप से मुड़ जाते हैं, तो स्पष्ट हो जाता है eval)।
गिल्स

thx, फिक्स्ड कि :-)
इकोक्स

4
Eval और backticks के बीच अंतर क्या है?
जॉनीटेक्स

5
बैकटिक्स एक और पूरे शेल को निष्पादित करने के लिए शॉर्टहैंड हैं, जिसका अर्थ है कि आपके स्क्रिप्ट के भीतर एक और बच्चा बैश / श प्रक्रिया चल रही होगी।
एरोन आर।

क्यों गूंज $ y (चरण 3) $ फू के बजाय फू (10) वापस लाता है? (यानी स्ट्रिंग के बदले फू का मूल्य $ + फू का मूल्य)?
जॉनडोए

60

हाँ, evalएक bash आंतरिक कमांड है इसलिए इसे bashमैन पेज में वर्णित किया गया है ।

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.

आमतौर पर इसका उपयोग कमांड सबस्टीट्यूशन के साथ संयोजन में किया जाता है । एक स्पष्ट के बिना eval, शेल एक कमांड प्रतिस्थापन के परिणाम को निष्पादित करने की कोशिश करता है , न कि इसका मूल्यांकन करने के लिए।

यह कहें कि आप इसके बराबर कोड चाहते हैं VAR=value; echo $VAR। इस बात पर ध्यान दें कि शेल किस तरह से लिखता है echo VAR=value:

  1. andcoz@...:~> $( echo VAR=value )
    bash: VAR=value: command not found
    andcoz@...:~> echo $VAR
    <empty line>
    

    शेल निष्पादित करने की कोशिश करता है echoऔर VAR=valueदो अलग-अलग कमांड के रूप में। यह दूसरी स्ट्रिंग के बारे में एक त्रुटि फेंकता है। असाइनमेंट अप्रभावी रहता है।

  2. andcoz@...:~> eval $( echo VAR=value )
    andcoz@...:~> echo $VAR
    value
    
    शेल दो स्ट्रिंग्स को मिलाता है (समेटता है) echoऔर VAR=valueउपयुक्त नियमों के अनुसार इस एकल इकाई को पार्स करता है और इसे निष्पादित करता है।

अंतिम लेकिन कम से कम, evalएक बहुत ही खतरनाक आदेश हो सकता है। evalकमांड के किसी भी इनपुट को सुरक्षा समस्याओं से बचने के लिए सावधानी से जांचना चाहिए।


18

evalइसका कोई मैन पेज नहीं है क्योंकि यह एक अलग बाहरी कमांड नहीं है, बल्कि एक शेल इन-बिल्ट है, जिसका अर्थ है एक कमांड जिसे आंतरिक और शेल द्वारा ही जाना जाता है ( bash)। bashमैन पेज का प्रासंगिक हिस्सा कहता है:

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

इसके अलावा, उत्पादन अगर 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एक शक्तिशाली आदेश है और यदि आप इसका उपयोग करने का इरादा रखते हैं, तो आपको इसके साथ आने वाले संभावित सुरक्षा जोखिमों का सामना करने के लिए बहुत सावधान रहना चाहिए ।


16

Eval statement शेल को eval के तर्कों को कमांड के रूप में लेने और कमांड-लाइन के माध्यम से चलाने के लिए कहता है। यह नीचे जैसी स्थिति में उपयोगी है:

आपकी स्क्रिप्ट में यदि आप एक कमांड को एक चर में परिभाषित कर रहे हैं और बाद में आप उस कमांड का उपयोग करना चाहते हैं तो आपको eval का उपयोग करना चाहिए:

/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 >

3
आपके उदाहरण के लाइन 4 में टिप्पणी गलत है: यह होना चाहिए "उपरोक्त कमांड ने काम नहीं किया क्योंकि बैश ने एक कमांड को खोजने की कोशिश की ls | more। दूसरे शब्दों में: एकल कमांड नाम में नौ वर्ण शामिल हैं, जिसमें रिक्त स्थान और पाइप प्रतीक शामिल हैं ।
सीएफआई

मुझे ठीक वैसा ही व्यवहार मिलता है जैसा उन्होंने रिपोर्ट किया था। bash --version == GNU bash, संस्करण 3.2.57 (1) -release (x86_64-apple-darwin18)
अलेक्जेंडर बर्ड

10

Eval क्या है?

eval एक शेल कमांड है, जिसे आमतौर पर बिलिन के रूप में लागू किया जाता है।

POSIX में यह "2.14 के भाग के रूप में सूचीबद्ध है प्रवेश " eval "में विशेष निर्मित उपयोगिताएँ "
बिलिन का अर्थ क्या है:

"अंतर्निहित" शब्द का अर्थ है कि शेल सीधे उपयोगिता को निष्पादित कर सकता है और इसके लिए खोज करने की आवश्यकता नहीं है।

यह क्या करता है?

सरल शब्दों में: दो बार पार्स किए जाने के लिए एक इनपुट लाइन बनाता है ।

इससे ऐसा कैसे होता है?

शेल में चरणों का एक क्रम होता है जो एक पंक्ति को "प्रोसेस" करता है। आप इस छवि को देख सकते हैं और महसूस कर सकते हैं कि eval एकमात्र ऐसी रेखा है जो ऊपर जाती है, वापस चरण 1 पर, बाईं ओर। से POSIX विवरण :

2.1 शैल परिचय

  1. खोल पढ़ता है इसका इनपुट…।
  2. शेल इनपुट को टोकन में तोड़ता है: शब्द और ऑपरेटर
  3. शेल इनपुट को सरल और यौगिक कमांड में देता है।
  4. खोल विभिन्न विस्तार (अलग से) करता है ...
  5. शेल पुनर्निर्देशन करता है और पैरामीटर सूची से पुनर्निर्देशन ऑपरेटरों और उनके ऑपरेंड को निकालता है।
  6. शेल एक फंक्शन, बिल्ट-इन, एग्जीक्यूटेबल फाइल या स्क्रिप्ट को निष्पादित करता है ...
  7. शेल वैकल्पिक रूप से कमांड के बाहर निकलने की स्थिति को पूरा करने के लिए इंतजार करता है।

चरण 6 में एक अंतर्निहित कार्य निष्पादित किया जाएगा।
स्टेप 6 में एवल प्रोसेस्ड लाइन को स्टेप 1 पर वापस भेजने का कारण बनता है।
यह एकमात्र ऐसी स्थिति है जिसके तहत निष्पादन अनुक्रम वापस जाता है।

इसलिए मैं कहता हूं: eval के साथ एक इनपुट लाइन दो बार पार्स होती है ।

दो बार पार्स करने के प्रभाव।

सबसे पहला।

और सबसे महत्वपूर्ण प्रभाव समझने के लिए। क्या पहली बार एक पंक्ति ऊपर दिखाए गए सात शेल चरणों के अधीन है, उद्धृत कर रहा है । चरण 4 (विस्तार) के अंदर, सभी विस्तार करने के लिए चरणों का एक क्रम भी है , जिनमें से अंतिम भाग उद्धरण हटाना है :

उद्धरण हटाने को हमेशा अंतिम प्रदर्शन किया जाएगा।

इसलिए, हमेशा, हटाए जाने का एक स्तर है।

दूसरा।

उस पहले प्रभाव के परिणामस्वरूप, पंक्ति के अतिरिक्त / अलग-अलग हिस्से शेल पार्सिंग और अन्य सभी चरणों के संपर्क में आ जाते हैं।

उदाहरण।

अविवेक।

यह अप्रत्यक्ष विस्तार को निष्पादित करने की अनुमति देता है:

a=b b=c    ;    eval echo \$$a            ### shall produce "c"

क्यों? क्योंकि पहले लूप पर, पहले $को उद्धृत किया जाता है।
इस प्रकार, इसे शेल द्वारा विस्तार के लिए नजरअंदाज कर दिया जाता है। नाम के साथ
अगला $"बी" के उत्पादन के लिए विस्तारित है।
फिर, एक स्तर के उद्धरण को हटा दिया जाता है, जिससे पहला $अयोग्य हो जाता है।
पहले लूप का अंत।

यह तब है, दूसरे लूप पर कि स्ट्रिंग $bशेल द्वारा पढ़ा जाता है।
फिर "ग" तक विस्तारित किया गया
और एक तर्क के रूप में दिया गया echo

"लूप" को देखने के लिए पहले लूप पर क्या उत्पादन होगा (फिर से मूल्यांकन किया जाना है), प्रतिध्वनि का उपयोग करें। या कोई कमांड / स्क्रिप्ट / प्रोग्राम जो स्पष्ट रूप से तर्कों को दर्शाता है:

$ a=b b=c
$ eval echo \$$a;
c

इको द्वारा प्रतिस्थापित "क्या हो रहा है" को देखने के लिए:

$ echo echo \$$a
echo $b

एक पंक्ति के सभी "भागों" को दिखाना संभव है:

$ printf '<%s> ' echo \$$a
<echo> <$b>

जो, इस उदाहरण में, केवल एक प्रतिध्वनि और एक चर है, लेकिन अधिक जटिल मामलों का मूल्यांकन करने में मदद करने के लिए इसे याद रखें।

एक सुधार।

यह कहा जाना चाहिए कि: ऊपर दिए गए कोड में कोई गलती है, क्या आप इसे देख सकते हैं?
आसान: कुछ उद्धरण गायब हैं।

कैसे? आप पूछ सकते हैं। सरल, चलिए चर बदलते हैं (कोड नहीं):

$ a=b b="hi     jk"
$ eval echo \$$a
hi jk

लापता रिक्त स्थान देखें?
ऐसा इसलिए है क्योंकि अंदर $bका मूल्य शेल द्वारा विभाजित किया गया था।

यदि वह आपको मना नहीं करता है, तो यह प्रयास करें:

$ a=b b="hi  *  jk"
$ eval echo \$$a              ### warning this will expand to the list  
                              ### of all files in the present directory.

क्यों?

छूटी हुई बोली। इसे सही ढंग से काम करने के लिए (आंतरिक "$a"और बाहरी \"उद्धरण जोड़ें )।
यह कोशिश करो (पूरी तरह से सुरक्षित है):

$ a=b b="hi      *       jk"
$ eval echo \" \$"$a" \"
hi      *       jk

मैनुअल के बारे में:

इसके लिए कोई मैन पेज नहीं है ।।

नहीं, इसके लिए एक स्वतंत्र मैन पेज नहीं है। मैनुअल के साथ man -f evalया यहां तक apropos evalकि नो एंट्री के लिए खोज ।

यह अंदर शामिल है man bash। जैसा कि कोई भी बिल्ट-इन है।
"शेल बिल्डिन कॉमन्ड्स" और फिर "ईवैल" के लिए खोजें।

सहायता प्राप्त करने का एक आसान तरीका है: बैश में, आप help evalबिल्ट-इन के लिए मदद देखने के लिए कर सकते हैं ।

बुराई को बुराई क्यों कहा जाता है?

क्योंकि यह पाठ को गतिशील रूप से कोड करने के लिए बाध्यकारी है।

दूसरे शब्दों में: यह अपने तर्कों की सूची (और / या ऐसे तर्कों के विस्तार) को एक निष्पादित पंक्ति में परिवर्तित करता है। यदि किसी कारण से, एक हमलावर द्वारा एक तर्क निर्धारित किया गया है, तो आप हमलावर कोड निष्पादित करेंगे।

या और भी सरल, जो आप बता रहे हैं कि जिसने भी एक या कई तर्कों के मूल्य को परिभाषित किया है:

चलो, यहाँ बैठो और कोई भी कमांड लाइन टाइप करो, मैं इसे अपनी शक्तियों के साथ निष्पादित करूँगा।

क्या वह खतरनाक है? हर किसी के लिए स्पष्ट होना चाहिए कि यह है।

Eval के लिए सुरक्षा नियम होना चाहिए:
केवल उन चरों पर eval निष्पादित करें, जिनके लिए आपने इसे दिया है।

और अधिक विस्तार से पढ़ें ।


10

evalसबसे व्याख्या की भाषाओं (की एक विशेषता है TCL, python, ruby...), न केवल गोले। इसका उपयोग कोड का गतिशील रूप से मूल्यांकन करने के लिए किया जाता है।

गोले में, यह शेल बिल्ड कमांड के रूप में कार्यान्वित किया जाता है।

मूल रूप से, evalएक स्ट्रिंग को तर्क के रूप में लेता है और इसमें कोड का मूल्यांकन / व्याख्या करता है। गोले में, evalएक से अधिक तर्क ले सकते हैं, लेकिन evalमूल्यांकन करने के लिए स्ट्रिंग बनाने के लिए सिर्फ उन्हें समेटते हैं।

यह बहुत शक्तिशाली है क्योंकि आप कोड को गतिशील रूप से बना सकते हैं और इसे चला सकते हैं, कुछ ऐसा जो आप संकलित भाषाओं में नहीं कर सकते हैं जैसे C।

पसंद:

varname=$1 varvalue=$2
eval "$varname=\$varvalue" # evaluate a string like "foo=$varvalue"
                           # which in Bourne-like shell language
                           # is a variable assignment.

लेकिन यह खतरनाक भी है क्योंकि डायनामिक (बाहरी रूप से प्रदान किए गए) पुर्जों को पवित्र करना महत्वपूर्ण है क्योंकि इसे evalशेल कोड के रूप में व्याख्या किए जाने वाले कारण के लिए पारित किया गया है ।

उदाहरण के लिए, यदि ऊपर $1है evil-command; var, तो शेल कोड का evalमूल्यांकन करना होगा evil-command; var=$varvalueऔर फिर उसे चलाना होगा evil-command

की बुराई evalअक्सर अतिरंजित होती है।

ठीक है, यह खतरनाक है, लेकिन कम से कम हम जानते हैं कि यह खतरनाक है।

अगर की तरह (खोल के आधार पर),, स्वच्छ नहीं अन्य आदेशों का एक बहुत अपने तर्कों में खोल कोड का मूल्यांकन करेंगे [उर्फ test, export, printf, जीएनयू sed, awkऔर निश्चित रूप से sh/ bash/ perlऔर सभी व्याख्याकार ...

उदाहरण (यहाँ का उपयोग कर unameके रूप में evil-commandऔर $aके रूप में बाहर से unsanitized डेटा प्रदान की गई):

$ 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

उन sed, export... आदेशों अधिक खतरनाक माना जा सकता है क्योंकि जब यह स्पष्ट है eval "$var"की सामग्री के कारण होगा $varखोल कोड के रूप में मूल्यांकन किया जाना है, यह इतना स्पष्ट साथ है sed "s/foo/$var/"या export "$var=value"या [ "$var" -gt 0 ]। ख़तरनाकता समान है, लेकिन यह उन अन्य आदेशों में छुपा है।


@BinaryZebra, sedजैसे evalकि एक चर में निहित स्ट्रिंग पारित किया जा रहा है, और दोनों के लिए, उस स्ट्रिंग की सामग्री को शेल कोड के रूप में मूल्यांकन किया जा रहा है, इसलिए sedयह उतना ही खतरनाक है eval, जितना कि मैं कह रहा हूं। sedपास किया जा रहा है एक स्ट्रिंग युक्त uname(uname को अब तक निष्पादित नहीं किया गया है) और के मंगलाचरण के माध्यम से sed, uname कमांड निष्पादित किया जाता है। जैसे eval के लिए। में sed 's/foo/$a/g', आप अनजान डेटा को पास नहीं कर रहे हैं sed, यह वह नहीं है जिसके बारे में हम यहाँ बात कर रहे हैं।
स्टीफन चेज़लस

2

यह उदाहरण कुछ प्रकाश बहा सकता है:

#!/bin/bash
VAR1=25
VAR2='$VAR1'
VAR3='$VAR2'
echo "$VAR3"
eval echo "$VAR3"
eval eval echo "$VAR3"

उपरोक्त स्क्रिप्ट का आउटपुट:

$VAR2
$VAR1
25

आपके योगदान के लिए धन्यवाद, लेकिन, जैसा कि वे मनोरंजक हैं, हम वास्तव में उपयोग की (थोड़ा अलग) उदाहरणों की एक सूची को संकलित करने में रुचि नहीं रखते हैं eval। क्या आप मानते हैं कि evalमौजूदा जवाबों में इस तरह की कार्यक्षमता के कुछ मूलभूत, महत्वपूर्ण पहलू शामिल नहीं हैं? यदि हां, तो इसे समझाएं , और अपने स्पष्टीकरण को स्पष्ट करने के लिए उदाहरण का उपयोग करें। कृपया टिप्पणियों में प्रतिक्रिया न दें;  इसे स्पष्ट और अधिक पूर्ण बनाने के लिए अपना उत्तर संपादित करें।
स्कॉट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.