Kaip nustatyti kintamąjį komandos išėjimui į bash?

Turiu gana paprastą scenarijų, kuris atrodo taip:

 #!/bin/bash VAR1="$1" MOREF='sudo run command against $VAR1 | grep name | cut -c7-' echo $MOREF 

Kai paleidžiu šį scenarijų iš komandų eilutės ir perduodu argumentus, gaunu jokių rezultatų. Tačiau, kai paleidžiu $MOREF kintamajame esančias komandas, galiu gauti išvestį.

Norėčiau žinoti, kaip galėčiau atlikti komandos, kuri turėtų būti vykdoma scenarijuje, rezultatus, išsaugoti jį kintamajame ir tada išleisti šį kintamąjį į ekraną?

1162
10 янв. Johnas nustatė sausio 10 d 2011-01-10 23:58 '11, 23:58, 2011-01-10 23:58
@ 13 atsakymų

Be `command` ( `command` ), galite naudoti $(command) , kurią man lengviau skaityti, ir leidžia lizdus.

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

Citavimo ( " ) reikšmė yra svarbi daugialypės vertės išsaugojimui.

1761 m
11 янв. Atsakymą pateikė Andy Lester 11 sausis 2011-01-11 00:04 '11 12:04 am. 2011-01-11 00:04

Atnaujinimas (2018): teisingas kelias

 $(sudo run command) 

border=0

Jūs naudojate netinkamą apaštalą. Jums nereikia. Šis simbolis vadinamas „backticks“ (arba „rimtu akcentu“).

Patinka tai:

 #!/bin/bash VAR1="$1" VAR2="$2" MOREF='sudo run command against "$VAR1" | grep name | cut -c7-' echo "$MOREF" 
209
11 янв. Ilya Kogan atsakė sausio 11 d 2011-01-11 00:00 '11 ne 0:00 2011-01-11 00:00

Kaip jie jums nurodė, turite naudoti „atgalines žymes“.

Siūloma $(command) alternatyva taip pat veikia ir yra lengviau skaityti, tačiau atkreipkite dėmesį, kad ji galioja tik su bash arba korn korpusais (ir iš jų gautais korpusais), todėl, jei jūsų scenarijai turi būti tikrai nešiojami skirtingose ​​„Unix“ sistemas, turėtumėte pirmenybę teikti seniems pavadinimams.

58
12 янв. atsakymas pateikiamas bitwelder Jan 12 2011-01-12 01:14 '11 at 1:14 2011-01-12 01:14

Žinau tris būdus, kaip tai padaryti:

1) Funkcijos, tinkamos tokioms užduotims atlikti:

 func (){ ls -l } 

Paskambinkite jam, sakydamas func

2) Galima įvertinti kitą tinkamą sprendimą:

 var="ls -l" eval $var 

3) Trečiasis naudojamas tiesioginius kintamuosius:

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

Trečiojo sprendimo rezultatą galite gauti geru būdu:

 echo "$var" 

ir taip pat bjaurus:

 echo $var 
47
13 февр. Atsakymą pateikė MLSC vasario 13 d. 2014-02-13 10:31 '14, 10:31 AM 2014-02-13 10:31

Kai kurie „ gudrybės, naudojami nustatant kintamuosius iš komandų

2-asis redagavimas 2018-02-12: specialiojo kelio pridėjimas, žr. Pačioje jo apačioje!

2018-01-25 Redaguoti: pridėti mėginio funkciją (užpildyti vars apie diskus)

Pirmasis yra paprastas ir suderintas būdas.

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

Labiausiai suderinamas, antras būdas

Dėl to lizdavimas gali tapti sunkus

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

Įdėtas mėginys:

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

skaityti daugiau nei vieną kintamąjį (su bachizmu)

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

Jei tik noriu naudoti vertę:

 array=($(df -k /)) 

Galite matyti masyvo kintamąjį:

 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]="/")' 

Tada:

 echo ${array[9]} 529020 

Bet aš tai norėčiau:

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

Pirmas read foo tiesiog praleis antraštės eilutę ( $foo kintamasis turi kažką panašaus į „ Filesystem 1K-blocks Used Available Use% Mounted on )

Kai kurių kintamųjų užpildymo funkcijos pavyzdys:

 #!/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 

Nota: declare eilutė nereikalinga, tik skaitymui.

Apie sudo cmd | grep... | cut... sudo cmd | grep... | cut... 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 

(Prašome išvengti nereikalingos cat ! Taigi, tai tik 1 mažesnis kištukas:

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

Visi vamzdžiai ( | ) reiškia kištukus. Jei reikia atlikti kitą procesą, prieiga prie diskų, bibliotekos skambučių ir kt.

Todėl naudojant „ sed “ mėginiui, subprocesas apribojamas tik viena šakute:

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

Ir su buggy:

Tačiau daugeliui veiksmų, daugiausia dėl mažų failų, „ galėjo atlikti šį darbą pats:

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

arba

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

Toliau apie kintamąjį skaidymą ...

Pažvelkite į mano atsakymą: Kaip suskirstyti eilutę pagal ribotuvą bash?

Alternatyva: šakių pjaustymas naudojant ilgalaikes fonines užduotis

2. rev. Redagavimas 2018-02-12: norint išvengti kelių šakių

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

arba

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

Ir nuo date ir bc gali veikti eilutėse:

 bc -l <<<$'3*4\n5*6' 12 30 date -f - +%s < <(ps ho lstart 1 $$) 1516030449 1517853288 

Jei norite iš naujo dirbti, galėtume naudoti ilgą foninį procesą, nereikia paleisti naujo prijungimo kiekvieno užklausos atveju:

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

(žinoma, FD 5 ir 6 turėtų būti nenaudojami!) ... Iš čia galite naudoti šį procesą:

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

Funkcijoje newConnector

Mano naująjį „Connector“ funkciją galite rasti „ GitHub.Com“ arba savo svetainėje („Nota on github“, mano svetainėje yra du failai, funkcija ir demonstracija įtrauktos į vieną failą, kurį galima naudoti naudojimui ar tiesiog demonstravimui)

Pavyzdys:

 . 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 funkcija leidžia naudoti foninį darbą su paprasta datos sintaksė:

 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 

Iš ten, jei norite užbaigti vieną iš foninių procesų, tiesiog reikia jį uždaryti:

 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 

kurių nereikia, nes visi fd yra uždaryti pagrindinio proceso pabaigoje.

41
20 дек. Atsakymą pateikė F. Hauri . 2016-12-20 10:06 '16 at 10:06 2016-12-20 10:06

Tiesiog būkite skirtingi:

 MOREF=$(sudo run command against $VAR1 | grep name | cut -c7-) 
22
11 янв. „ DigitalRoss“ atsakymas sausio 11 d 2011-01-11 00:07 '11 prie 0:07 2011-01-11 00:07

Nustatydami kintamąjį, įsitikinkite, kad prieš ir po ženklo = neturite vietos . Aš tiesiog praleidžiau valandą bandydamas išsiaiškinti, bandydamas surasti visus sprendimus! Tai nėra kietas.

Teisingas:

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

Nesėkmė su klaida: (medžiaga: nerasta arba panaši)

 WTFF= `echo "stuff"` echo "Example: $WTFF" 
12
18 июля '17 в 14:42 2017-07-18 14:42 Atsakymą davė Emil liepos 18 d. 17 val. 14:42 2017-07-18 14:42

Jei norite tai padaryti su daugiašaliu / keliais komandomis / s, galite tai padaryti:

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

Arba:

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

Pavyzdys:

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

Išvada:

 first second third 

Naudodamiesi heredoc , galite lengvai supaprastinti situaciją, sulaužydami ilgą vienos eilutės kodą į daugialypį. Kitas pavyzdys:

 output="$( ssh -p $port $user@$domain <<EOF #breakdown your long ssh command into multiline here. EOF )" 
12
01 июня '15 в 20:38 2015-06-01 20:38 atsakymas pateiktas Jahid 01 birželio 15 d. 20:38 2015-06-01 20:38

Galite naudoti atvirkštinius (taip pat vadinamus diakritiniais kapais) arba $() . Pavyzdžiui, kaip

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

Abu turi tą patį poveikį. Tačiau OUTPUT = $ (x + 2) yra lengviau skaitomas ir paskutinis.

5
09 февр. Atsakymas pateikiamas Pratik Patil 09 vasario 9 d. 2016-02-09 11:03 '16 at 11:03 2016-02-09 11:03

Tai dar vienas būdas, kurį galite naudoti su kai kuriais teksto redaktoriais, kurie negali teisingai pasirinkti kiekvieno sukurto sudėtinio kodo.

 read -r -d '' str < <(cat somefile.txt) echo "${#str}" echo "$str" 
4
11 мая '15 в 0:44 2015-05-11 00:44 „ Aquarius Power“ atsakymas gegužės 11, 15 d. 0:44 2015-05-11 00:44

Taip pat turėtumėte naudoti

$(command-here)

arba

 'command-here' 

pavyzdys

 #!/bin/bash VAR1="$1" VAR2="$2" MOREF="$(sudo run command against "$VAR1" | grep name | cut -c7-)" echo "$MOREF" 
4
29 дек. Atsakymą pateikė Diego Velez 29 d. 2017-12-29 02:44 '17 at 2:44 2017-12-29 02:44

Kai kurie tai gali būti naudingi. Bendrosios vertės kintamojo pakeitimo atveju, kai triukas naudoja $(()) dvigubą skliaustą:

 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 
3
22 нояб. Atsakymas duotas Gus 22 lapkričio. 2015-11-22 14:59 '15, 14:59 pm 2015-11-22 14:59

Toliau pateikiami du būdai:

Atminkite, kad erdvė yra labai svarbi . Taigi, jei norite, kad jūsų komanda būtų paleista, naudokite kaip be pridėjus daugiau tarpų.

  1. kitas paskiria harshil L ir spausdina jį.

     L=$"harshil" echo "$L" 
  2. Toliau tr komandų išvestis priskiriama L2. tr dirba su kitu kintamuoju L1.

     L2=$(echo "$L1" | tr [:upper:] [:lower:]) 
0
22 июня '16 в 13:09 2016-06-22 13:09 atsakymą Harshil pateikė birželio 16 d. 16 val. 13:09 2016-06-22 13:09

Kiti klausimai apie etiketes arba Užduoti klausimą