Vad är kommandosubstitution i ett skal? [duplicera]

<åt sidan class = "s-notice s-notice__info js-post-notice mb16" role = "status">

Den här frågan har redan svar här :

Kommentarer

  • OK, alla måste slappna av och sluta anklaga varandra för trolling. Om du inte gillar ' gillar du en fråga, nedrösta eller ignorera den och gå bort . Om du känner att du ' attackeras i kommentarer, engagera dig inte utan flagga och gå bort .
  • Också relaterad: Vad ' är skillnaden mellan $ (stuff) och `stuff ?
  • Visar utdata från ett kommando med kommandosubstitution och 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 skrivas date | sed 's/^/Today is /'
  • @Kusalananda Jag ser din mening att skriva ut det omedelbart (med printf ) är värdelös. Jag ändrade formuleringen lite, från omedelbart till sometime later, är det mer tilltalande?
  • Exemplet kan vara thedate=$(date), följt av printf 'The date is %s\n' "$thedate".

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.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *