Reacties
Antwoord
" Commandosubstitutie " is de naam van het kenmerk van de shell-taal waarmee je een commando kunt uitvoeren en de uitvoer van dat commando kunt laten vervangen ( vervangt) de tekst van het commando.
Er is geen ander kenmerk van de shell-taal waarmee je dat kunt doen.
Een commando-vervanging, dwz de hele $(...)
expressie, wordt vervangen door zijn uitvoer, wat het primaire gebruik van opdrachtvervangingen is.
De opdracht die de opdrachtvervanging uitvoert, wordt uitgevoerd in een subshell, wat betekent dat het zijn eigen omgeving heeft die de omgeving van de bovenliggende shell niet beïnvloedt.
Niet alle subshell-uitvoeringen zijn commandosubstituties, hoewel ugh (zie verdere voorbeelden aan het einde).
Voorbeeld dat laat zien dat een opdrachtvervanging wordt uitgevoerd in een subshell:
$ s=123 $ echo "hello $( s=world; echo "$s" )" hello world $ echo "$s" 123
Hier, de variabele s
is ingesteld op de tekenreeks 123
. Op de volgende regel wordt echo
aangeroepen op een string die het resultaat van een opdrachtvervanging bevat. Het commando substitutie stelt s
in op de string world
en herhaalt deze string. De string world
is de uitvoer van de opdracht in de opdrachtvervanging en dus, als deze werd uitgevoerd onder set -x
, zouden we zien dat de tweede regel hierboven zou zijn uitgebreid naar echo "hello world"
, wat hello world
op de terminal produceert:
$ set -x $ echo "hello $( s=world; echo "$s" )" ++ s=world ++ echo world + echo "hello world" hello world
(bash
voegt een extra niveau +
prompts toe aan elk niveau van een opdrachtvervangingssubshell in de trace-uitvoer, andere shells doen dit misschien niet)
Ten slotte laten we zien dat de opdracht binnen de opdrachtvervanging in zijn eigen subshell werd uitgevoerd, omdat het geen invloed had op de waarde van s
in de aanroepende shell (de waarde van s
is nog steeds 123
, niet world
).
Er zijn andere situaties waarin opdrachten worden uitgevoerd in subshells, zoals in
echo "hello" | read message
In bash
, tenzij u de optie lastpipe
instelt (alleen in niet-interactieve instanties), wordt de read
uitgevoerd in een subshell, wat betekent dat $message
zal niet worden gewijzigd in de bovenliggende shell, dwz echo "$message"
doen na het bovenstaande commando zal een lege string weergeven (of welke waarde $message
was eerder).
Een procesvervanging in bash
wordt ook uitgevoerd in een subshell:
cat < <( echo "hello world" )
Ook dit verschilt van een commando-vervanging.
Reacties
- Voor bash 4.2 up, als shopt lastpipe is ingesteld, taakbeheer niet actief is en de pijplijn geen achtergrond heeft, wordt het laatste commando niet uitgevoerd in een subshell.
- U zegt: “Er is geen ander kenmerk van de shell-taal waarmee u dat kunt doen.” Welnu, met het risico haren te splijten, kunt u
cmd₁ > myfile
/read -r var < myfile
/cmd₂ "$var"
doen . Indien nodig kunt u dat uitbreiden om meerregelige gegevens te verwerken. - @ G-Man Ja, en u kunt ook een nieuw shellscript naar een bestand schrijven en dat uitvoeren.Er is echter geen andere functie die een manier biedt om een stuk tekst te vervangen door de uitvoer van een commando.
Antwoord
a=$(command)
slaat de resultaatwaarde van command
op in de variabele.
Er is echt niet meer aan de hand.
Als een kanttekening denk ik:
a=`command`
is verouderd en heeft de dezelfde betekenis als hierboven.
Reacties
- resultaat hier is de standaarduitvoer van het commando ontdaan van alle nieuwe regel tekens (en enkele variaties tussen shells als de uitvoer geen tekst is). Merk op dat
`...`
de Bourne van csh-syntaxis is, terwijl$(...)
de Korn / POSIX-syntaxis is (met`...`
nog steeds ondersteund voor achterwaartse compatibiliteit) - @St é phaneChazelas Bedankt voor waardevolle informatie, en voel je vrij om het antwoord te bewerken om het op te nemen.
echo
is een slecht voorbeeld van opdrachtvervanging omdat 1) de uitvoer toch zou zijn weergegeven, 2)printf
is veiliger te gebruiken voor variabele gegevens. Het voorbeeld kan net zo goed worden geschrevendate | sed 's/^/Today is /'
printf
) is nutteloos. Ik heb de formulering een beetje veranderd, van onmiddellijk naarsometime later
, is het aantrekkelijker?thedate=$(date)
, gevolgd doorprintf 'The date is %s\n' "$thedate"
.