Komentáře
Odpověď
" Substituce příkazů " je název funkce jazyka shellu, který vám umožňuje provést příkaz a nechat výstup tohoto příkazu nahradit ( substitute) text příkazu.
Neexistuje žádná jiná funkce jazyka shellu, která by vám to umožňovala.
Substituce příkazu, tj. celá $(...)
výraz, je nahrazen jeho výstupem, který je primárním použitím substitucí příkazů.
Příkaz, který se provádí substitucí příkazu, se provádí v subshell, což znamená, že má své vlastní prostředí, které nebude mít vliv na prostředí nadřazeného prostředí.
Ne všechna provedení subshell jsou substitutami příkazů fuj (viz další příklady na konci).
Příklad ukazující, že substituce příkazu je provedena v subshellu:
$ s=123 $ echo "hello $( s=world; echo "$s" )" hello world $ echo "$s" 123
Zde je proměnná s
je nastavena na řetězec 123
. Na dalším řádku je echo
vyvolán na řetězci obsahujícím výsledek nahrazení příkazu. Substituce příkazu nastaví s
na řetězec world
a ozve se tento řetězec. Řetězec world
je výstup příkazu v substituci příkazu , a tedy pokud byl spuštěn pod set -x
, uvidíme, že druhý řádek výše by byl rozšířen na echo "hello world"
, který na terminálu vytvoří hello world
:
$ set -x $ echo "hello $( s=world; echo "$s" )" ++ s=world ++ echo world + echo "hello world" hello world
(bash
přidává další úroveň výzev +
na každou úroveň Substituce nahrazení příkazu ve výstupu trasování, ostatní skořápky to nemusí dělat.
Nakonec ukážeme, že příkaz uvnitř substituce příkazu byl spuštěn ve vlastní podsestavě, protože neovlivnil hodnotu s
ve volajícím shellu (hodnota s
je stále 123
, ne world
).
Existují i jiné situace, kdy jsou příkazy prováděny v dílčích skořápkách, například v
echo "hello" | read message
V bash
, pokud nenastavíte možnost lastpipe
(pouze v neinteraktivních případech), provede se read
v subshelmu, což znamená že $message
se v nadřazeném prostředí nezmění, tj. echo "$message"
poté, co výše uvedený příkaz ozve prázdný řetězec (nebo jakoukoli hodnotu $message
byl předtím).
Substituce procesu v bash
se také provádí v subshellu:
cat < <( echo "hello world" )
Toto je také odlišné od nahrazení příkazu.
Komentáře
- Pro verzi bash 4.2 up, pokud shopt lastpipe je nastaven, řízení úloh není aktivní a kanál není na pozadí, poslední příkaz se nespustí v subshellu.
- Říkáte: „Neexistuje žádná jiná funkce jazyka shellu, která by vám to umožňovala.“ S rizikem štěpení vlasů můžete
cmd₁ > myfile
/read -r var < myfile
/cmd₂ "$var"
. V případě potřeby to můžete rozšířit tak, aby zpracovávalo víceřádkové údaje. - @ G-Man Ano, můžete také do souboru napsat nový skript prostředí a provést jej.Neexistuje žádná jiná funkce, která by poskytovala způsob nahrazení části textu výstupem příkazu.
Odpovědět
a=$(command)
uloží do proměnné výslednou hodnotu command
.
Už to opravdu není.
Jako vedlejší poznámku se domnívám:
a=`command`
byl zastaralý a má stejný význam jako výše.
Komentáře
- výsledek zde je standardní výstup příkazu zbaveného všech jeho koncových nových řádků znaků (a některé rozdíly mezi skořápkami, pokud je výstup netextový). Všimněte si, že
`...`
je Bourneova syntaxe csh, zatímco$(...)
je syntaxe Korn / POSIX (s`...`
stále podporováno z důvodu zpětné kompatibility) - @St é phaneChazelas Děkujeme za cenné informace a neváhejte upravit odpověď tak, aby je obsahovala.
echo
je špatným příkladem substituce příkazu, protože 1) výstup by byl stejně zobrazen, 2)printf
je bezpečnější použít pro variabilní data. Příklad by mohl být také napsándate | sed 's/^/Today is /'
printf
) je k ničemu. Trochu jsem změnil frázování z okamžitě nasometime later
, je to přitažlivější?thedate=$(date)
, následujeprintf 'The date is %s\n' "$thedate"
.