Wat is opdrachtvervanging in een shell? [duplicate]

Deze vraag heeft hier al antwoorden :

Reacties

  • OK, iedereen moet zich ontspannen en elkaar niet langer beschuldigen van trollen. Als je een vraag ' niet leuk vindt, stem dan omlaag of negeer hem en loop weg . Als je denkt dat je ' wordt aangevallen in reacties, doe dan niet mee, maar markeer en loop weg .
  • Ook gerelateerd: Wat is ' is het verschil tussen $ (stuff) en `stuff`?
  • De uitvoer van een opdracht met behulp van opdrachtvervanging en 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 geschreven date | sed 's/^/Today is /'
  • @Kusalananda Ik begrijp uw punt dat u het onmiddellijk afdrukt (met printf ) is nutteloos. Ik heb de formulering een beetje veranderd, van onmiddellijk naar sometime later, is het aantrekkelijker?
  • Het voorbeeld zou thedate=$(date), gevolgd door printf 'The date is %s\n' "$thedate".

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.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *