एक तर्क के रूप में पिछले कमांड के आउटपुट को पास करें


117

मेरे पास एक कमांड है जो डेटा को stdout ( command1 -p=aaa -v=bbb -i=4) में आउटपुट करता है । आउटपुट लाइन में निम्न मान हो सकते हैं:

rate (10%) - name: value - 10Kbps

मैं उस आउटपुट को 'रेट' स्टोर करने के लिए तैयार करना चाहता हूं (मुझे लगता है कि पाइप यहां उपयोगी होगा)। और अंत में, मैं उस दर को एक दूसरे कमांड पर एक पैरामीटर का मान होना चाहूंगा (मान लीजिए command2 -t=${rate})

यह मेरी तरफ से मुश्किल लग रहा है; मैं बेहतर तरीके से जानना चाहता हूं कि पाइप, ग्रीप, सेड और इतने पर कैसे उपयोग करें।

मैंने उस तरह के बहुत सारे संयोजन आज़माए हैं लेकिन मैं इनसे भ्रमित हो रहा हूँ:

$ command1 -p=aaa -v=bbb -i=4 | grep "rate" 2>&1 command2 -t="rate was "${rate}

जवाबों:


142

आप दो बहुत भिन्न प्रकार के इनपुटों को भ्रमित कर रहे हैं।

  1. मानक इनपुट ( stdin)
  2. कमांड लाइन तर्क

ये अलग हैं, और विभिन्न उद्देश्यों के लिए उपयोगी हैं। कुछ कमांड दोनों तरीकों से इनपुट ले सकते हैं, लेकिन वे आम तौर पर उन्हें अलग तरीके से उपयोग करते हैं। उदाहरण के लिए wcकमांड लें :

  1. पासिंग इनपुट stdin:

    ls | wc -l
    

    इस के उत्पादन में लाइनों की गणना करेगा ls

  2. कमांड लाइन तर्कों द्वारा इनपुट पास करना:

    wc -l $(ls)
    

    यह प्रिंट की गई फ़ाइलों की सूची में लाइनों की गणना करेगाls

पूरी तरह से अलग चीजें।

अपने प्रश्न का उत्तर देने के लिए, ऐसा लगता है कि आप पहले कमांड के आउटपुट से दर को कैप्चर करना चाहते हैं, और फिर दूसरी कमांड के लिए कमांड लाइन तर्क के रूप में दर का उपयोग करें। यहाँ ऐसा करने का एक तरीका है:

rate=$(command1 | sed -ne 's/^rate..\([0-9]*\)%.*/\1/p')
command2 -t "rate was $rate"

का स्पष्टीकरण sed:

  • s/pattern/replacement/आदेश कुछ पैटर्न को बदलने के लिए है
  • पैटर्न का अर्थ है: पंक्ति को "दर" ( ^rate) के बाद किसी भी दो वर्ण ( ..), 0 या उससे अधिक अंकों के बाद %, उसके बाद, पाठ के बाकी हिस्सों ( .*) के साथ शुरू करना चाहिए
  • \1प्रतिस्थापन में इसका मतलब है कि पहली अभिव्यक्ति की सामग्री भीतर कैप्चर की गई है \(...\), इसलिए इस स्थिति में %साइन से पहले अंक
  • -nका झंडा sedआदेश डिफ़ॉल्ट रूप से लाइनों मुद्रित नहीं का मतलब है। pके अंत में s///कमांड लाइन मुद्रित करने के लिए अगर वहाँ एक प्रतिस्थापन था मतलब है। संक्षेप में, कमांड केवल कुछ प्रिंट करेगा यदि कोई मैच था।

12

मैं इसका उपयोग करता हूं:

command1 | xargs -I{} command2 {}

command1प्रतिस्थापन (ब्रेसिज़) का उपयोग करके xargs के माध्यम से आउटपुट पास करें command2। यदि कमांड 1 का findउपयोग करना बंद कर दिया गया है और अशक्त समाप्त तारों के लिए -print0जोड़ना सुनिश्चित हो जाएगा, और प्रत्येक चीज़ के लिए कॉल किया जाएगा ।-0xargsxargscommand2

आपके मामले में (और @Janos से sed लाइन लेते हुए):

command1 -p=aaa -v=bbb -i=4 | sed -ne 's/^rate..\([0-9]*\)%.*/\1/p' | xargs -I{} command2 -t="rate was {}"

इससे चीजें अच्छी रहती हैं और मुझे यह पसंद है।
मतीन उल्हाक

4

उत्पादन का अनुकरण करने के लिए command1मैं इस गूंज बयान उपयोग कर रहा हूँ:

$ echo -e "Foo\nrate (10%) - name: value - 10Kbps\nBar"
$ alias command1='echo -e "Blah\nrate (10%) - name: value - 10Kbps\nBlag"'

एक त्वरित परीक्षण:

$ command1
Blah
rate (10%) - name: value - 10Kbps
Blag

यह सब अच्छा है, इसलिए इसे बाहर पार्स करें:

$ command1 | grep 'rate'
rate (10%) - name: value - 10Kbps

तो हम उस लाइन को प्राप्त करते हैं जिसे हम बाहर चाहते हैं command1, इसे पास करते हैं command2:

$ alias command2='echo'
$ command2 -t="rate was "$(command1 | grep 'rate')
-t=rate was rate (10%) - name: value - 10Kbps

मैं "rate was "$(command1 | grep 'rate')अपने आप समाप्‍त होने की उम्‍मीद कर रहा हूं । यदि वह व्हाट्सएप की वजह से काम नहीं करता है, तो आपको इसके बजाय इनपुट को पास करने में सक्षम होना चाहिए:

$ alias command2='echo'
$ command2 -t=$(echo '"rate was ' $(command1 | grep 'rate') '"')
-t="rate was rate (10%) - name: value - 10Kbps "


2

पहला काम उस लाइन से रेट निकालना है। जीएनयू जीआरईपी (गैर-एम्बेडेड लिनक्स या सिगविन) के साथ, आप -oविकल्प का उपयोग कर सकते हैं । आप जो भाग चाहते हैं, वह केवल अंकों वाला और उसके बाद एक %चिह्न है। यदि आप %स्वयं को नहीं निकालना चाहते हैं , तो आपको एक अतिरिक्त ट्रिक की आवश्यकता है: एक शून्य-चौड़ाई वाला दिखने वाला मुखर , जो कुछ भी नहीं बल्कि केवल उसी से मेल खाता है, जिसके बाद कुछ भी नहीं है %

command1 -p=aaa -v=bbb -i=4 | grep -o -P '[0-9]+(?=%)'

एक और संभावना है कि सेड का उपयोग किया जाए। एक लाइन में से एक हिस्से को सेड में निकालने के लिए, sकमांड का उपयोग करें , एक रेगेक्स के साथ जो पूरी लाइन (साथ शुरू ^होने और समाप्त होने $) से मेल खाता है , एक समूह ( \(…\)) में बनाए रखने के लिए । रखने के लिए समूह (ओं) की सामग्री से पूरी लाइन बदलें। सामान्य तौर पर, -nडिफ़ॉल्ट प्रिंटिंग को बंद करने के लिए विकल्प को पास करें और pसंशोधक को प्रिंट लाइनों में डाल दें जहां निकालने के लिए कुछ है (यहां एक ही लाइन है इसलिए यह कोई फर्क नहीं पड़ता)। मिलते-जुलते पैटर्न के बाद केवल एक लाइन के हिस्से को देखें और अधिक सेड ट्रिक्स के लिए आसपास के वर्णों को प्रिंट किए बिना 'सेड' के साथ मिलान किए गए एक रेग्क्स को निकालें।

command1 -p=aaa -v=bbb -i=4 | sed 's/^.*rate(\([0-9]*\)%).*$/\1/'

पालकी की तुलना में अधिक लचीला फिर से जागृत है। Awk एक छोटी अनिवार्यता वाली भाषा में प्रत्येक पंक्ति के लिए निर्देश निष्पादित करता है। यहां दर निकालने के कई तरीके हैं; मैं दूसरे फ़ील्ड का चयन करता हूं (फ़ील्ड डिफ़ॉल्ट रूप से व्हाट्सएप द्वारा सीमांकित की जाती हैं), और इसमें सभी वर्णों को हटा दें जो एक अंक नहीं हैं।

command1 -p=aaa -v=bbb -i=4 | awk '{gsub(/[^0-9]+/, "", $2); print $2}'

अगला कदम, अब जब आपने रेट निकाला है, तो इसे एक तर्क के रूप में पास करना है command2। उस के लिए उपकरण एक कमांड सुस्पष्टीकरण है । यदि आप एक कमांड $(…)(डॉलर-कोष्ठक) के अंदर रखते हैं , तो इसका आउटपुट कमांड लाइन में प्रतिस्थापित किया जाता है। कमांड का आउटपुट प्रत्येक व्हाट्सएप ब्लॉक पर अलग-अलग शब्दों में विभाजित होता है, और प्रत्येक शब्द वाइल्डकार्ड पैटर्न के रूप में माना जाता है; जब तक आप ऐसा नहीं चाहते, कमांड प्रतिस्थापन के चारों ओर दोहरे उद्धरण रखें "$(…)":। दोहरे उद्धरण चिह्नों के साथ, कमांड के आउटपुट का उपयोग सीधे एकल पैरामीटर के रूप में किया जाता है (केवल परिवर्तन यह है कि आउटपुट के अंत में newlines हटा दिए जाते हैं)।

command2 -t "$(command1 -p=aaa -v=bbb -i=4 |
               sed 's/^.*rate(\([0-9]*\)%).*$/\1/')"

0

आप उपयोग कर सकते हैं grepऔर यह पीसीआरई - पर्ल कम्पेटिबल रेगुलर एक्सप्रेशंस है। यह आपको परिणाम के लिए स्ट्रिंग के "रेट" को शामिल किए बिना, जब इसके लिए grepping कर रहा है, तो आपके मूल्य के साथ मिलान करने के लिए एक लुकअप का उपयोग करने की अनुमति देता है।

उदाहरण

$ echo "rate (10%) - name: value - 10Kbps" | grep -oP '(?<=^rate \()\d+'
10

विवरण

उपरोक्त grepकार्य निम्नानुसार हैं:

  • -oकेवल वही लौटाएगा \d+, जो हम खोज रहे हैं , जो कि परगनों के भीतर का अंक है।
  • -P grep की PCRE सुविधा को सक्षम करता है
  • (?<=^rate \() केवल "दर" के साथ शुरू होने वाले तार लौटाएगा

command2

"दर" के मूल्य को पकड़ने के लिए आप command1जैसे चाहें दौड़ सकते हैं :

$ rate=$(command 1 | grep -oP '(?<=^rate \()\d+'

फिर अपने दूसरे आदेश के लिए आप बस उस चर का उपयोग करेंगे।

$ command2 -t=${rate}

आप कल्पना कर सकते हैं और यह सब एक पंक्ति बना सकते हैं:

$ command2 -t=$(command1 | grep -oP '(?<=^rate \()\d+')

यह $(..)निष्पादन ब्लॉक के अंदर कमांड 1 को निष्पादित करेगा , इसके परिणाम लेगा और उन्हें कमांड 2 के -t=..स्विच में शामिल करेगा ।


0

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

procstat -r `pgrep -x foo`

यहाँ, pgrep का उपयोग प्रक्रिया foo के PID को निकालने के लिए किया जाता है जो कि procstat कमांड में जाता है जो PID की प्रक्रिया को तर्क के रूप में लेता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.