Kommentarer
Svar
" Kommandosubstitution " är namnet på funktionen i skalspråket som låter dig utföra ett kommando och få utgången från det kommandot att ersättas ( ersätta) kommandoteksten.
Det finns ingen annan funktion i skalspråket som gör att du kan göra det.
Ett kommandosubstitution, dvs. hela $(...)
-uttryck rsätts med dess utdata, vilket är den primära användningen av kommandosubstitutioner.
Kommandot som kommandosubstitutionen körs utförs i en subshell, vilket betyder att den har sin egen miljö som inte påverkar moderns skalmiljö.
Inte alla subshell-körningar är kommandosubstitutioner ugh (se ytterligare exempel i slutet).
Exempel som visar att en kommandosubstitution utförs i en subshell:
$ s=123 $ echo "hello $( s=world; echo "$s" )" hello world $ echo "$s" 123
Här är variabel s
är inställd på strängen 123
. På nästa rad anropas echo
på en sträng som innehåller resultatet av en kommandosubstitution. Kommandosubstitutionen ställer in s
till strängen world
och ekar denna sträng. Strängen world
är kommandos utdata i kommandosubstitutionen och om detta kördes under set -x
skulle vi se att den andra raden ovan skulle ha utökats till echo "hello world"
, vilket producerar hello world
på terminalen:
$ set -x $ echo "hello $( s=world; echo "$s" )" ++ s=world ++ echo world + echo "hello world" hello world
(bash
lägger till en extra nivå av +
till varje nivå av en kommandosubstitutionsunderskal i spårningsutgången, andra skal kanske inte gör detta)
Slutligen visar vi att kommandot inuti kommandosubstitutionen kördes i sin egen subshell, eftersom det inte påverkade värdet på s
i det anropande skalet (värdet för s
är fortfarande 123
, inte world
).
Det finns andra situationer där kommandon körs i subshells, till exempel i
echo "hello" | read message
I bash
, om du inte ställer in alternativet lastpipe
(endast i icke-interaktiva fall), körs read
i en subshell, vilket betyder att $message
inte kommer att ändras i det överordnade skalet, det vill säga att göra echo "$message"
efter ovanstående kommando kommer att ge en tom sträng (eller vilket värde som helst $message
var tidigare).
En processersättning i bash
körs också i en subshell:
cat < <( echo "hello world" )
Även detta skiljer sig från en kommandosubstitution.
Kommentarer
- För bash 4.2 upp, om shopt lastpipe är inställt, jobbkontroll inte är aktiv och rörledningen inte har bakgrund, körs det sista kommandot inte i en subshell.
- Du säger, ”Det finns ingen annan funktion i skalspråket som gör att du kan göra det.” Nåväl, med risk för att klyfta hår kan du göra
cmd₁ > myfile
/read -r var < myfile
/cmd₂ "$var"
. Om det behövs kan du utvidga det för att hantera data med flera rader. - @ G-Man Ja, och du kan också skriva ut ett nytt skalskript till en fil och utföra det.Det finns ingen annan funktion som ger ett sätt att ersätta en textbit med utdata från ett kommando.
Svar
a=$(command)
lagrar resultatvärdet för command
i variabeln.
Det finns egentligen inte mer.
Som en sidoanteckning tror jag:
a=`command`
har avskaffats och har samma betydelse som ovan.
Kommentarer
- resultat här är standardutgången för kommandot avskalad från all dess efterföljande nya tecken (och vissa variationer mellan skalen om utdata inte är text). Observera att
`...`
är Bourne för csh-syntax medan$(...)
är Korn / POSIX-syntaxen (med`...`
stöds fortfarande för bakåtkompatibilitet) - @St é phaneChazelas Tack för värdefull information och gärna redigera svaret så att det inkluderas.
echo
är ett dåligt exempel på kommandosubstitution eftersom 1) utdata skulle ha visats ändå, 2)printf
är säkrare att använda för variabel data. Exemplet kan lika gärna skrivasdate | sed 's/^/Today is /'
printf
) är värdelös. Jag ändrade formuleringen lite, från omedelbart tillsometime later
, är det mer tilltalande?thedate=$(date)
, följt avprintf 'The date is %s\n' "$thedate"
.