Kommentarer
Svar
" Kommandosubstitusjon " er navnet på funksjonen til skallspråket som lar deg utføre en kommando og få utgangen til den kommandoen erstattet ( erstatte) teksten til kommandoen.
Det er ingen andre funksjoner i skallspråket som lar deg gjøre det.
En kommandosubstitusjon, dvs. hele $(...)
uttrykk, erstattes med utdata, som er den primære bruken av kommandosubstitusjoner.
Kommandoen kommandosubstitusjonen utfører, utføres i en subshell, som betyr at det har sitt eget miljø som ikke vil påvirke det overordnede skallets miljø.
Ikke alle subshell-henrettelser er kommandosubstitusjoner ugh (se flere eksempler på slutten).
Eksempel som viser at en kommandosubstitusjon utføres i en subshell:
$ s=123 $ echo "hello $( s=world; echo "$s" )" hello world $ echo "$s" 123
Her, variabel s
er satt til strengen 123
. På neste linje påkalles echo
på en streng som inneholder resultatet av en kommandosubstitusjon. Kommandosubstitusjonen setter s
til strengen world
og ekko denne strengen. Strengen world
er utgangen av kommandoen i kommandosubstitusjonen og dermed, hvis denne ble kjørt under set -x
, ville vi se at den andre linjen ovenfor ville blitt utvidet til echo "hello world"
, som produserer hello world
på terminalen:
$ set -x $ echo "hello $( s=world; echo "$s" )" ++ s=world ++ echo world + echo "hello world" hello world
(bash
legger til et ekstra nivå på +
ber om hvert nivå av en kommandosubstitusjonsunderskall i sporingsutgangen, andre skjell kan ikke gjøre dette)
Til slutt viser vi at kommandoen inne i kommandosubstitusjonen ble kjørt i sin egen subshell, fordi den ikke påvirket verdien av s
i det anropende skallet (verdien av s
er fortsatt 123
, ikke world
).
Det er andre situasjoner der kommandoer utføres i subshells, for eksempel i
echo "hello" | read message
I bash
, med mindre du angir lastpipe
-alternativet (bare i ikke-interaktive forekomster), blir read
utført i en subshell, som betyr at $message
ikke blir endret i det overordnede skallet, dvs. å gjøre echo "$message"
etter kommandoen ovenfor vil ekko en tom streng (eller hvilken som helst verdi $message
var før).
En prosessubstitusjon i bash
kjøres også i en subshell:
cat < <( echo "hello world" )
Også dette skiller seg fra en kommandosubstitusjon.
Kommentarer
- For bash 4.2 opp, hvis shopt lastpipe er satt, jobbkontroll ikke er aktiv, og rørledningen ikke er bakgrunn, kjører den siste kommandoen ikke i en subshell.
- Du sier, «Det er ingen andre funksjoner i skallspråket som lar deg gjøre det.» Vel, med fare for å dele håret, kan du gjøre
cmd₁ > myfile
/read -r var < myfile
/cmd₂ "$var"
. Om nødvendig kan du utvide det til å håndtere data med flere linjer. - @ G-Man Ja, og du kan også skrive ut et nytt skallskript til en fil og utføre det.Det er ingen andre funksjoner som gir en måte å erstatte et stykke tekst med utdataene fra en kommando.
Svar
a=$(command)
lagrer resultatverdien til command
i variabelen.
Det er egentlig ikke mer til det.
Som en sideanmerkning tror jeg:
a=`command`
er utfaset og har samme betydning som ovenfor.
Kommentarer
- resultat her er standardutgangen av kommandoen fjernet fra alle dens etterfølgende nye linje tegn (og noen variasjoner mellom skallene hvis utdataene ikke er tekst). Merk at
`...`
er Bourne av csh-syntaks mens$(...)
er Korn / POSIX-syntaksen (med`...`
støttes fremdeles for bakoverkompatibilitet) - @St é phaneChazelas Takk for verdifull informasjon, og rediger gjerne svaret for å inkludere det.
echo
er et dårlig eksempel på kommandosubstitusjon fordi 1) utdata ville ha blitt vist uansett, 2)printf
er tryggere å bruke for variable data. Eksemplet kan like godt skrivesdate | sed 's/^/Today is /'
printf
) er ubrukelig. Jeg endret formuleringen litt, fra umiddelbart tilsometime later
, er det mer tiltalende?thedate=$(date)
, etterfulgt avprintf 'The date is %s\n' "$thedate"
.