bash - बैश में कमांड के आउटपुट में चर को कैसे सेट करें?
shell command-line (9)
कुछ 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
जिसकी आवश्यकता नहीं है, क्योंकि मुख्य प्रक्रिया खत्म होने पर सभी एफडी बंद हो जाते हैं।
मेरे पास एक बहुत ही सरल लिपि है जो निम्न की तरह कुछ है:
#!/bin/bash
VAR1="$1"
MOREF='sudo run command against $VAR1 | grep name | cut -c7-'
echo $MOREF
जब मैं कमांड लाइन से इस स्क्रिप्ट को चलाता हूं और इसे तर्क देता हूं, तो मुझे कोई आउटपुट नहीं मिल रहा है। हालांकि, जब मैं $MOREF
चर के भीतर निहित आदेश चलाता हूं, तो मैं आउटपुट प्राप्त करने में सक्षम हूं।
मैं जानना चाहता हूं कि कोई स्क्रिप्ट के भीतर चलाने के लिए एक कमांड के परिणाम कैसे ले सकता है, इसे एक चर में सहेज सकता है, और फिर स्क्रीन पर उस चर को आउटपुट कर सकता है?
आप बैक-टिक (जिसे उच्चारण कब्र के रूप में भी जाना जाता है) या $()
उपयोग कर सकते हैं। जैसे-
OUTPUT=$(x+2);
OUTPUT=`x+2`;
दोनों का एक ही प्रभाव है। लेकिन OUTPUT = $ (x + 2) अधिक पठनीय और नवीनतम है।
एक चर सेट करते समय सुनिश्चित करें कि आपके पास पहले और / या = चिह्न के बाद कोई स्थान नहीं है । सचमुच एक घंटे बिताए, यह समझने की कोशिश कर रहा है, सभी प्रकार के समाधानों की कोशिश कर रहा है! यह अच्छा नहीं है।
सही बात:
WTFF=`echo "stuff"`
echo "Example: $WTFF"
त्रुटि के साथ विफल हो जाएगा : (सामान: नहीं मिला या समान)
WTFF= `echo "stuff"`
echo "Example: $WTFF"
कुछ इसे उपयोगी पा सकते हैं। परिवर्तनीय प्रतिस्थापन में पूर्णांक मान, जहां चाल $(())
डबल ब्रैकेट का उपयोग कर रही है:
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
बस अलग होना:
MOREF=$(sudo run command against $VAR1 | grep name | cut -c7-)
बैकटीक्स के अलावा, आप $()
उपयोग कर सकते हैं, जिसे मुझे पढ़ने में आसान लगता है, और घोंसले की अनुमति देता है।
OUTPUT="$(ls -1)"
echo "${OUTPUT}"
उद्धरण ( "
) बहु-पंक्ति मानों को संरक्षित करने के लिए महत्वपूर्ण है।
यदि आप इसे 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
)"
यह एक और तरीका है, कुछ पाठ संपादकों के साथ उपयोग करना अच्छा है जो आपके द्वारा बनाए गए प्रत्येक जटिल कोड को सही ढंग से हाइलाइट करने में असमर्थ हैं।
read -r -d '' str < <(cat somefile.txt)
echo "${#str}"
echo "$str"
अद्यतन (2018): सही तरीका है
$(sudo run command)
आप गलत प्रकार के एस्ट्रोफ़े का उपयोग कर रहे हैं। आपको '
नहीं, '
आवश्यकता है। इस चरित्र को "बैकटिक्स" (या "गंभीर उच्चारण" कहा जाता है)।
इस कदर:
#!/bin/bash
VAR1="$1"
VAR2="$2"
MOREF=`sudo run command against "$VAR1" | grep name | cut -c7-`
echo "$MOREF"