for i in $(xrandr); do echo "$i" ; donefor i in "$(xrandr)"; do echo "$i"; donefor 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
$IFSodpoví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
$IFSna výchozí hodnotu (nebo ji zrušte), aby se rozdělila na mezery - Použijte
set -fzakázat generování názvu souboru, pokud si nejste jisti, žexrandrnikdy 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='
'