आप eval
कमांड के साथ क्या कर सकते हैं ? क्यों उपयोगी है? क्या यह किसी प्रकार का बना-बनाया कार्य है जो बैश में है? इसका कोई man
पृष्ठ नहीं है ।।
help eval
अपने खोल से "आदमी" पृष्ठ पाने के लिए
आप eval
कमांड के साथ क्या कर सकते हैं ? क्यों उपयोगी है? क्या यह किसी प्रकार का बना-बनाया कार्य है जो बैश में है? इसका कोई man
पृष्ठ नहीं है ।।
help eval
अपने खोल से "आदमी" पृष्ठ पाने के लिए
जवाबों:
eval
POSIX का हिस्सा है। इसका एक इंटरफ़ेस जो एक शेल निर्मित हो सकता है।
इसका वर्णन "पॉसिक्स प्रोग्रामर मैनुअल" में दिया गया है: 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
$foo
मूल्य के साथ '10'
और $x
मूल्य के साथ 'foo'
।$y
, जिसमें तार शामिल हैं '$foo'
। डॉलर के चिन्ह के साथ बच जाना चाहिए '$'
।echo $y
।'$foo'
eval
। यह पहले $x
स्ट्रिंग का मूल्यांकन करेगा 'foo'
। अब हमारे पास वह वक्तव्य है y=$foo
जिसका मूल्यांकन किया जाएगा y=10
।echo $y
अब मूल्य है '10'
।यह कई भाषाओं में एक सामान्य कार्य है, जैसे पर्ल और जावास्क्रिप्ट। अधिक उदाहरणों के लिए perldoc eval पर एक नज़र डालें: http://perldoc.perl.org/functions/eval.html
eval
एक अंतर्निहित, एक फ़ंक्शन है। व्यवहार में, बिल्ट-इन बहुत सारे कार्यों की तरह व्यवहार करता है, जिसमें इन-लैंग्वेज की परिभाषा नहीं होती है, लेकिन काफी (जैसा कि यदि आप एक फ़ंक्शन को परिभाषित करने के लिए पर्याप्त रूप से मुड़ जाते हैं, तो स्पष्ट हो जाता है eval
)।
हाँ, 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
:
andcoz@...:~> $( echo VAR=value )
bash: VAR=value: command not found
andcoz@...:~> echo $VAR
<empty line>
शेल निष्पादित करने की कोशिश करता है echo
और VAR=value
दो अलग-अलग कमांड के रूप में। यह दूसरी स्ट्रिंग के बारे में एक त्रुटि फेंकता है। असाइनमेंट अप्रभावी रहता है।
andcoz@...:~> eval $( echo VAR=value )
andcoz@...:~> echo $VAR
value
शेल दो स्ट्रिंग्स को मिलाता है (समेटता है) echo
और VAR=value
उपयुक्त नियमों के अनुसार इस एकल इकाई को पार्स करता है और इसे निष्पादित करता है।अंतिम लेकिन कम से कम, eval
एक बहुत ही खतरनाक आदेश हो सकता है। eval
कमांड के किसी भी इनपुट को सुरक्षा समस्याओं से बचने के लिए सावधानी से जांचना चाहिए।
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
एक शक्तिशाली आदेश है और यदि आप इसका उपयोग करने का इरादा रखते हैं, तो आपको इसके साथ आने वाले संभावित सुरक्षा जोखिमों का सामना करने के लिए बहुत सावधान रहना चाहिए ।
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 >
ls | more
। दूसरे शब्दों में: एकल कमांड नाम में नौ वर्ण शामिल हैं, जिसमें रिक्त स्थान और पाइप प्रतीक शामिल हैं ।
eval एक शेल कमांड है, जिसे आमतौर पर बिलिन के रूप में लागू किया जाता है।
POSIX में यह "2.14 के भाग के रूप में सूचीबद्ध है । प्रवेश " eval "में विशेष निर्मित उपयोगिताएँ " ।
बिलिन का अर्थ क्या है:
"अंतर्निहित" शब्द का अर्थ है कि शेल सीधे उपयोगिता को निष्पादित कर सकता है और इसके लिए खोज करने की आवश्यकता नहीं है।
सरल शब्दों में: दो बार पार्स किए जाने के लिए एक इनपुट लाइन बनाता है ।
शेल में चरणों का एक क्रम होता है जो एक पंक्ति को "प्रोसेस" करता है। आप इस छवि को देख सकते हैं और महसूस कर सकते हैं कि eval एकमात्र ऐसी रेखा है जो ऊपर जाती है, वापस चरण 1 पर, बाईं ओर। से POSIX विवरण :
2.1 शैल परिचय
- खोल पढ़ता है इसका इनपुट…।
- शेल इनपुट को टोकन में तोड़ता है: शब्द और ऑपरेटर
- शेल इनपुट को सरल और यौगिक कमांड में देता है।
- खोल विभिन्न विस्तार (अलग से) करता है ...
- शेल पुनर्निर्देशन करता है और पैरामीटर सूची से पुनर्निर्देशन ऑपरेटरों और उनके ऑपरेंड को निकालता है।
- शेल एक फंक्शन, बिल्ट-इन, एग्जीक्यूटेबल फाइल या स्क्रिप्ट को निष्पादित करता है ...
- शेल वैकल्पिक रूप से कमांड के बाहर निकलने की स्थिति को पूरा करने के लिए इंतजार करता है।
चरण 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 निष्पादित करें, जिनके लिए आपने इसे दिया है।
और अधिक विस्तार से पढ़ें ।
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 ]
। ख़तरनाकता समान है, लेकिन यह उन अन्य आदेशों में छुपा है।
sed
जैसे eval
कि एक चर में निहित स्ट्रिंग पारित किया जा रहा है, और दोनों के लिए, उस स्ट्रिंग की सामग्री को शेल कोड के रूप में मूल्यांकन किया जा रहा है, इसलिए sed
यह उतना ही खतरनाक है eval
, जितना कि मैं कह रहा हूं। sed
पास किया जा रहा है एक स्ट्रिंग युक्त uname
(uname को अब तक निष्पादित नहीं किया गया है) और के मंगलाचरण के माध्यम से sed
, uname कमांड निष्पादित किया जाता है। जैसे eval के लिए। में sed 's/foo/$a/g'
, आप अनजान डेटा को पास नहीं कर रहे हैं sed
, यह वह नहीं है जिसके बारे में हम यहाँ बात कर रहे हैं।
यह उदाहरण कुछ प्रकाश बहा सकता है:
#!/bin/bash
VAR1=25
VAR2='$VAR1'
VAR3='$VAR2'
echo "$VAR3"
eval echo "$VAR3"
eval eval echo "$VAR3"
उपरोक्त स्क्रिप्ट का आउटपुट:
$VAR2
$VAR1
25
eval
। क्या आप मानते हैं कि eval
मौजूदा जवाबों में इस तरह की कार्यक्षमता के कुछ मूलभूत, महत्वपूर्ण पहलू शामिल नहीं हैं? यदि हां, तो इसे समझाएं , और अपने स्पष्टीकरण को स्पष्ट करने के लिए उदाहरण का उपयोग करें। कृपया टिप्पणियों में प्रतिक्रिया न दें; इसे स्पष्ट और अधिक पूर्ण बनाने के लिए अपना उत्तर संपादित करें।
type command
किस प्रकार की है यह जानने के लिए उपयोग करें । ( ths मामले में)type eval