for i in $(xrandr); do echo "$i" ; done
for i in "$(xrandr)"; do echo "$i"; done
for i in "$(xrandr)"; do echo $i; done
Chápu, proč se 1 liší od 2. Ale proč 3 dává jiný výstup než 2? Vysvětlete prosím také výstup. Jak fungují uvozovky na nových řádcích?
Přijatá odpověď:
Proměnná bez uvozovek (jako v $var
) nebo substituce příkazů (jako v $(cmd)
nebo `cmd`
) je split+glob operátor v Bourneovských shellech.
To znamená, že jejich obsah je rozdělen podle aktuální hodnoty $IFS
speciální proměnná (která standardně obsahuje znaky mezery, tabulátoru a nového řádku)
A pak každé slovo, které je výsledkem tohoto rozdělení, podléhá generování názvu souboru (také známé jako globbing nebo rozšíření názvu souboru ), to znamená, že jsou považovány za vzory a jsou rozšířeny na seznam souborů, které tomuto vzoru odpovídají.
Takže v for i in $(xrandr)
, $(xrandr)
, protože není v uvozovkách, je rozdělen na sekvence mezer, tabulátorů a znaků nového řádku. A každé slovo, které je výsledkem tohoto rozdělení, je kontrolováno na shodu názvů souborů (nebo ponecháno tak, jak je, pokud neodpovídají žádnému souboru) a for
smyčky přes všechny.
V for i in "$(xrandr)"
, nepoužíváme operátor split+glob jako náhradu příkazu je citován, takže na jednom je ve smyčce jeden průchod hodnota:výstup xrandr
(bez znaků na konci nového řádku, které příkazy nahrazují proužky).
Nicméně v echo $i
, $i
je opět bez uvozovek, takže opět obsah $i
je rozdělen a podléhá generování názvu souboru a ty jsou předány jako samostatné argumenty do echo
příkaz (a echo
vypíše své argumenty oddělené mezerami).
Takže poučení:
- pokud nechcete rozdělování slov nebo generování názvu souboru , vždy citujte expanze proměnných a substituce příkazů
- pokud chcete rozdělení slov nebo generování názvu souboru , ponechte je bez uvozovek, ale nastavte
$IFS
odpovídajícím způsobem a/nebo v případě potřeby povolit nebo zakázat generování názvu souboru (set -f
,set +f
).
Pokud ve vašem příkladu výše obvykle chcete procházet prázdným odděleným seznamem slov ve výstupu xrandr
, budete potřebovat:
- opusťte
$IFS
na výchozí hodnotu (nebo ji zrušte), aby se rozdělila na mezery - Použijte
set -f
zakázat generování názvu souboru, pokud si nejste jisti, žexrandr
nikdy nevypíše žádné*
nebo?
nebo[
znaky (což jsou zástupné znaky používané ve vzorech generování souborů)
A poté použijte pouze operátor split+glob (pouze substituci příkazu nebo expanzi proměnné ponechte bez uvozovek) v in
část for
smyčka:
set -f; unset -v IFS
for i in $(xrandr); do whatever with "$i"; done
Pokud chcete procházet (neprázdné) řádky xrandr
výstup, budete muset nastavit $IFS
na znak nového řádku:
IFS='
'