bash बैश में कमांड के आउटपुट में चर को कैसे सेट करें?




shell command-line (11)

जैसा कि वे पहले से ही आपको संकेत दे चुके हैं, आपको 'बैकटिक्स' का उपयोग करना चाहिए।

विकल्प प्रस्तावित $(command) काम करता है, और इसे पढ़ने में भी आसान है, लेकिन ध्यान दें कि यह केवल बैश या कॉर्न शैल (और उनसे प्राप्त गोले) के साथ मान्य है, इसलिए यदि आपकी स्क्रिप्ट को विभिन्न यूनिक्स पर वास्तव में पोर्टेबल होना है सिस्टम, आपको पुरानी बैकटिक्स नोटेशन पसंद करनी चाहिए।

मेरे पास एक बहुत ही सरल लिपि है जो निम्न की तरह कुछ है:

#!/bin/bash

VAR1="$1"    
MOREF='sudo run command against $VAR1 | grep name | cut -c7-'

echo $MOREF

जब मैं कमांड लाइन से इस स्क्रिप्ट को चलाता हूं और इसे तर्क देता हूं, तो मुझे कोई आउटपुट नहीं मिल रहा है। हालांकि, जब मैं $MOREF चर के भीतर निहित आदेश चलाता हूं, तो मैं आउटपुट प्राप्त करने में सक्षम हूं।

मैं जानना चाहता हूं कि कोई स्क्रिप्ट के भीतर चलाने के लिए एक कमांड के परिणाम कैसे ले सकता है, इसे एक चर में सहेज सकता है, और फिर स्क्रीन पर उस चर को आउटपुट कर सकता है?


यदि आप इसे multiline / एकाधिक कमांड / एस के साथ करना चाहते हैं तो आप यह कर सकते हैं:

output=$( bash <<EOF
#multiline/multiple command/s
EOF
)

या:

output=$(
#multiline/multiple command/s
)

उदाहरण:

#!/bin/bash
output="$( bash <<EOF
echo first
echo second
echo third
EOF
)"
echo "$output"

आउटपुट:

first
second
third

heredoc का उपयोग करके आप अपने लंबे एकल लाइन कोड को मल्टीलाइन में तोड़कर चीजों को आसानी से सरल बना सकते हैं। एक और उदाहरण:

output="$( ssh -p $port [email protected]$domain <<EOF 
#breakdown your long ssh command into multiline here.
EOF
)"

एक चर सेट करते समय सुनिश्चित करें कि आपके पास पहले और / या = चिह्न के बाद कोई स्थान नहीं है । सचमुच एक घंटे बिताए, यह समझने की कोशिश कर रहा है, सभी प्रकार के समाधानों की कोशिश कर रहा है! यह अच्छा नहीं है।

सही बात:

WTFF=`echo "stuff"`
echo "Example: $WTFF"

त्रुटि के साथ विफल हो जाएगा : (सामान: नहीं मिला या समान)

WTFF= `echo "stuff"`
echo "Example: $WTFF"

यह एक और तरीका है, कुछ पाठ संपादकों के साथ उपयोग करना अच्छा है जो आपके द्वारा बनाए गए प्रत्येक जटिल कोड को सही ढंग से हाइलाइट करने में असमर्थ हैं।

read -r -d '' str < <(cat somefile.txt)
echo "${#str}"
echo "$str"

आपको या तो उपयोग करने की ज़रूरत है

$(command-here)

या

`command-here`

उदाहरण

#!/bin/bash

VAR1="$1"
VAR2="$2"

MOREF=$(sudo run command against $VAR1 | grep name | cut -c7-)

echo $MOREF

मुझे करने के तीन तरीके पता हैं:

1) कार्य ऐसे कार्यों के लिए उपयुक्त हैं:

func (){
ls -l
}

Func कहकर इसे func

2) इसके अलावा एक और उपयुक्त समाधान eval किया जा सकता है:

var="ls -l"
eval $var

3) तीसरा एक चर का उपयोग कर रहा है:

var=$(ls -l)
OR
var=`ls -l`

आप अच्छे तरीके से तीसरे समाधान का आउटपुट प्राप्त कर सकते हैं:

echo "$var"

और भी बुरा तरीके से:

echo $var

आप बैक-टिक (जिसे उच्चारण कब्र के रूप में भी जाना जाता है) या $() उपयोग कर सकते हैं। जैसे-

OUTPUT=$(x+2);
OUTPUT=`x+2`;

दोनों का एक ही प्रभाव है। लेकिन OUTPUT = $ (x + 2) अधिक पठनीय और नवीनतम है।


यहां दो और तरीके दिए गए हैं: कृपया ध्यान रखें कि बैश में अंतरिक्ष बहुत महत्वपूर्ण है, इसलिए यदि आप चाहते हैं कि आपका आदेश चलाने के लिए बिना किसी रिक्त स्थान के उपयोग के है।

  1. निम्नलिखित एल को कठोर असाइन करता है और फिर इसे प्रिंट करता है

    L=$"harshil"
    echo "$L"
    
  2. निम्नलिखित L2 को कमांड tr के आउटपुट को निर्दिष्ट करता है। टी एक अन्य परिवर्तनीय एल 1 पर संचालित किया जा रहा है।

    L2=$(echo "$L1" | tr [:upper:] [:lower:])
    

कुछ इसे उपयोगी पा सकते हैं। परिवर्तनीय प्रतिस्थापन में पूर्णांक मान, जहां चाल $(()) डबल ब्रैकेट का उपयोग कर रही है:

N=3
M=3
COUNT=$N-1
ARR[0]=3
ARR[1]=2
ARR[2]=4
ARR[3]=1

while (( COUNT < ${#ARR[@]} ))
do
  ARR[$COUNT]=$((ARR[COUNT]*M))
  (( COUNT=$COUNT+$N ))
done

कुछ bash चाल जो मैं कमांड से चर सेट करने के लिए उपयोग करता हूं

दूसरा संपादित करें 2018-02-12: एक विशेष तरीका जोड़ना, इसके बहुत नीचे देखें!

2018-01-25 संपादित करें: नमूना फ़ंक्शन जोड़ें (डिस्क उपयोग के बारे में vars populating के लिए)

पहला सरल पुराना और संगत तरीका

myPi=`echo '4*a(1)' | bc -l`
echo $myPi 
3.14159265358979323844

अधिकतर संगत, दूसरा तरीका

चूंकि घोंसला भारी हो सकता है, इसके लिए कोष्ठक लागू किया गया था

myPi=$(bc -l <<<'4*a(1)')

नेस्टेड नमूना:

SysStarted=$(date -d "$(ps ho lstart 1)" +%s)
echo $SysStarted 
1480656334

एक से अधिक परिवर्तनीय पढ़ना ( bashisms के साथ)

df -k /
Filesystem     1K-blocks   Used Available Use% Mounted on
/dev/dm-0         999320 529020    401488  57% /

अगर मैं सिर्फ प्रयुक्त मूल्य चाहता हूं:

array=($(df -k /))

आप सरणी चर देख सकते हैं:

declare -p array
declare -a array='([0]="Filesystem" [1]="1K-blocks" [2]="Used" [3]="Available" [
4]="Use%" [5]="Mounted" [6]="on" [7]="/dev/dm-0" [8]="999320" [9]="529020" [10]=
"401488" [11]="57%" [12]="/")'

फिर:

echo ${array[9]}
529020

लेकिन मैं इसे पसंद करता हूं:

{ read foo ; read filesystem size used avail prct mountpoint ; } < <(df -k /)
echo $used
529020

पहला read foo केवल हेडर लाइन छोड़ देगा (परिवर्तनीय $foo Filesystem 1K-blocks Used Available Use% Mounted on जैसे कुछ Filesystem 1K-blocks Used Available Use% Mounted on )

कुछ चर पॉप्युलेट करने के लिए नमूना समारोह:

#!/bin/bash

declare free=0 total=0 used=0

getDiskStat() {
    local foo
    {
        read foo
        read foo total used free foo
    } < <(
        df -k ${1:-/}
    )
}

getDiskStat $1
echo $total $used $free

नोटा: पठनीयता के लिए declare लाइन की आवश्यकता नहीं है।

sudo cmd | grep ... | cut ... बारे में sudo cmd | grep ... | cut ... sudo cmd | grep ... | cut ...

shell=$(cat /etc/passwd | grep $USER | cut -d : -f 7)
echo $shell
/bin/bash

(कृपया बेकार cat से बचें! तो यह सिर्फ 1 कांटा कम है:

shell=$(grep $USER </etc/passwd | cut -d : -f 7)

सभी पाइप ( | ) कांटे का तात्पर्य है। जहां एक और प्रक्रिया को चलाने के लिए, डिस्क का उपयोग, पुस्तकालयों कॉल और इतने पर।

तो नमूना के लिए sed का उपयोग, subprocess केवल एक कांटा को सीमित कर देगा:

shell=$(sed </etc/passwd "s/^$USER:.*://p;d")
echo $shell

और bashisms के साथ:

लेकिन कई कार्रवाइयों के लिए, ज्यादातर छोटी फाइलों पर, bash खुद ही नौकरी कर सकता था:

while IFS=: read -a line ; do
    [ "$line" = "$USER" ] && shell=${line[6]}
  done </etc/passwd
echo $shell
/bin/bash

या

while IFS=: read loginname encpass uid gid fullname home shell;do
    [ "$loginname" = "$USER" ] && break
  done </etc/passwd
echo $shell $loginname ...

परिवर्तनीय विभाजन के बारे में आगे जा रहे हैं ...

मेरे जवाब पर एक नज़र डालें कि मैं बैश में एक डिलीमीटर पर स्ट्रिंग कैसे विभाजित करूं?

वैकल्पिक: पृष्ठभूमि लंबे समय से चलने वाले कार्यों का उपयोग करके कांटे को कम करना

दूसरा 2018-02-12 संपादित करें: जैसे कई कांटे को रोकने के लिए

myPi=$(bc -l <<<'4*a(1)'
myRay=12
myCirc=$(bc -l <<<" 2 * $myPi * $myRay ")

या

myStarted=$(date -d "$(ps ho lstart 1)" +%s)
mySessStart=$(date -d "$(ps ho lstart $$)" +%s)

और क्योंकि date और bc लाइन से लाइन काम कर सकता है:

bc -l <<<$'3*4\n5*6'
12
30

date -f - +%s < <(ps ho lstart 1 $$)
1516030449
1517853288

हम प्रत्येक अनुरोध के लिए नए कांटा शुरू किए बिना नौकरियों को दोबारा बनाने के लिए लंबी चल रही पृष्ठभूमि प्रक्रिया का उपयोग कर सकते हैं:

mkfifo /tmp/myFifoForBc
exec 5> >(bc -l >/tmp/myFifoForBc)
exec 6</tmp/myFifoForBc
rm /tmp/myFifoForBc

(बेशक, एफडी 5 और 6 का उपयोग नहीं किया जाना चाहिए!) ... वहां से, आप इस प्रक्रिया का उपयोग कर सकते हैं:

echo "3*4" >&5
read -u 6 foo
echo $foo
12

echo >&5 "pi=4*a(1)"
echo >&5 "2*pi*12"
read -u 6 foo
echo $foo
75.39822368615503772256

एक समारोह में newConnector

आपको newConnector पर या मेरी अपनी साइट पर मेरा GitHub.Com newConnector फ़ंक्शन मिल सकता है ( GitHub.Com पर नोटा, मेरी साइट पर दो फाइलें हैं, फ़ंक्शन और डेमो को 1 फ़ाइल में बंडल किया गया है जिसे उपयोग के लिए सोर्स किया जा सकता है या सिर्फ डेमो के लिए चलाया जा सकता है)

नमूना:

. shell_connector.sh

tty
/dev/pts/20

ps --tty pts/20 fw
    PID TTY      STAT   TIME COMMAND
  29019 pts/20   Ss     0:00 bash
  30745 pts/20   R+     0:00  \_ ps --tty pts/20 fw

newConnector /usr/bin/bc "-l" '3*4' 12

ps --tty pts/20 fw
    PID TTY      STAT   TIME COMMAND
  29019 pts/20   Ss     0:00 bash
  30944 pts/20   S      0:00  \_ /usr/bin/bc -l
  30952 pts/20   R+     0:00  \_ ps --tty pts/20 fw

declare -p PI
bash: declare: PI: not found

myBc '4*a(1)' PI
declare -p PI
declare -- PI="3.14159265358979323844"

फ़ंक्शन myBc आपको सरल वाक्यविन्यास के साथ पृष्ठभूमि कार्य का उपयोग करने देता है, और तिथि के लिए:

newConnector /bin/date '-f - +%s' @0 0
myDate '2000-01-01'
  946681200
myDate "$(ps ho lstart 1)" boottime
myDate now now ; read utm idl </proc/uptime
myBc "$now-$boottime" uptime
printf "%s\n" ${utm%%.*} $uptime
  42134906
  42134906

ps --tty pts/20 fw
    PID TTY      STAT   TIME COMMAND
  29019 pts/20   Ss     0:00 bash
  30944 pts/20   S      0:00  \_ /usr/bin/bc -l
  32615 pts/20   S      0:00  \_ /bin/date -f - +%s
   3162 pts/20   R+     0:00  \_ ps --tty pts/20 fw

वहां से, यदि आप पृष्ठभूमि प्रक्रिया में से एक को समाप्त करना चाहते हैं, तो आपको बस अपना एफडी बंद करना होगा:

eval "exec $DATEOUT>&-"
eval "exec $DATEIN>&-"
ps --tty pts/20 fw
    PID TTY      STAT   TIME COMMAND
   4936 pts/20   Ss     0:00 bash
   5256 pts/20   S      0:00  \_ /usr/bin/bc -l
   6358 pts/20   R+     0:00  \_ ps --tty pts/20 fw

जिसकी आवश्यकता नहीं है, क्योंकि मुख्य प्रक्रिया खत्म होने पर सभी एफडी बंद हो जाते हैं।


बैकटीक्स के अलावा, आप $() उपयोग कर सकते हैं, जिसे मुझे पढ़ने में आसान लगता है, और घोंसले की अनुमति देता है।

OUTPUT="$(ls -1)"
echo "${OUTPUT}"

उद्धरण ( " ) बहु-पंक्ति मानों को संरक्षित करने के लिए महत्वपूर्ण है।





command-line