एक चर में संग्रहीत कमांड को कैसे निष्पादित करें?


83

चर में संग्रहीत कुछ कमांड को कॉल करने का सही तरीका क्या है?
क्या 1 और 2 के बीच कोई अंतर है?

#!/bin/sh
cmd="ls -la $APPROOTDIR | grep exception"
#1
$cmd
#2
eval "$cmd"

7
कृपया BashFAQ / 050 देखें ।
डेनिस विलियमसन

जवाबों:


95

यूनिक्स गोले उन्हें निष्पादित करने से पहले इनपुट की प्रत्येक पंक्ति पर परिवर्तनों की एक श्रृंखला संचालित करते हैं। अधिकांश गोले के लिए यह कुछ इस तरह दिखता है ( bashमैनपेज से लिया गया ):

  • प्रारंभिक शब्द विभाजन
  • ब्रेस विस्तार
  • टिल्ड का विस्तार
  • पैरामीटर, चर और अंकगणितीय विस्तार
  • कमांड प्रतिस्थापन
  • द्वितीयक शब्द विभाजन
  • पथ विस्तार (उर्फ ग्लोबिंग)
  • उद्धरण निकालना

$cmdसीधे उपयोग करने से इसे पैरामीटर विस्तार चरण के दौरान आपकी कमांड द्वारा प्रतिस्थापित किया जाता है, और इसके बाद सभी परिवर्तनों का सामना करना पड़ता है।

का उपयोग करते eval "$cmd"हुए बोली हटाने के चरण तक कुछ भी नहीं होता है, जहां के $cmdरूप में लौटा दिया जाता है, और पैरामीटर के रूप में पास किया जाता हैeval , जिसका कार्य निष्पादित करने से पहले पूरी श्रृंखला को फिर से चलाना है।

इसलिए मूल रूप से, वे ज्यादातर मामलों में समान होते हैं, और जब आपकी कमांड पैरामीटर विस्तार तक परिवर्तन कदमों का उपयोग करती है, तो यह भिन्न होती है। उदाहरण के लिए, ब्रेस विस्तार का उपयोग करना:

$ cmd="echo foo{bar,baz}"
$ $cmd
foo{bar,baz}
$ eval "$cmd"
foobar foobaz

6
eval "$cmd"बिना लिखे कैसे करें eval? $($cmd)? ${$cmd}?
स्टीवन लू

2
@StevenLu, उनमें से कोई भी समकक्ष नहीं है - जानबूझकर ऐसा है: एक evalऑपरेशन सिंटैक्स के रूप में डेटा को पार्स करता है; यह इस प्रकार बहुत सुरक्षा के प्रति संवेदनशील है, और इसका अर्थ यह है कि यह बहुत खराब रूप होगा।
चार्ल्स डफी

5

यदि आप बस eval $cmd तब करते हैं जब हम करते हैं cmd="ls -l"(अंतःक्रियात्मक और एक स्क्रिप्ट में) हमें वांछित परिणाम मिलता है। आपके मामले में, आपके पास एक पैटर्न के बिना एक grep के साथ एक पाइप है, इसलिए grep भाग एक त्रुटि संदेश के साथ विफल हो जाएगा। बस $cmdएक "कमांड नहीं मिला" (या कुछ ऐसे) संदेश उत्पन्न करेगा। इसलिए eval का उपयोग करने का प्रयास करें और समाप्त कमांड का उपयोग करें, न कि कोई त्रुटि संदेश उत्पन्न करता है।


यह सिर्फ शरारत थी। "Grep अपवाद" होना चाहिए।
वलोडिमिर बेजुग्ली

इसके बाद eval का उपयोग करें, $ cmd का अपने आप से नहीं, क्योंकि यह शायद काम नहीं करेगा (यह मेरे परीक्षण में नहीं, बैश और ज़ी के तहत)। यह वही है जो करने का मतलब था ...
हेनो ब्रांडमा

0

$cmdकमांड लाइन पर निष्पादित किए जाने वाले मान के साथ बस चर को प्रतिस्थापित करेगा। eval "$cmd"कमांड लाइन पर परिणामी मूल्य को निष्पादित करने से पहले चर विस्तार और कमांड प्रतिस्थापन करता है

जब आप ऐसे कमांड चलाना चाहते हैं जो लचीला न हो, तो दूसरा तरीका मददगार है।
for i in {$a..$b}
प्रारूप लूप काम नहीं करेगा क्योंकि यह चर की अनुमति नहीं देता है।
इस स्थिति में, काटने या निकालने के लिए एक पाइप एक वर्कअराउंड है।

मैक OSX 10.6.8, बैश 3.2.48 पर परीक्षण किया गया


-4

मुझे लगता है कि आपको लगाना चाहिए

`

(backtick) अपने वैरिएबल के चारों ओर प्रतीक।


4
यह कमांड के आउटपुट को निष्पादित करता है, जो उदाहरण के लिए ls -l के मामले में "टोटल" कमांड नहीं मिला "जैसे संदेश उत्पन्न करेगा (क्योंकि कुल ... ls -l के आउटपुट का हिस्सा है, जैसे) तो यह है वह नहीं जो आप चाहते हैं।
हेन्नो ब्रांडमा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.