Po uruchomieniu tego polecenia:
ls
terminal wyświetla wynik działania ls.
Po uruchomieniu tego polecenia:
echo $(ls)
powłoka przechwytuje dane wyjściowe $(ls)i dokonuje na nich podziału słów . Przy ustawieniu domyślnym IFSoznacza to, że wszystkie sekwencje białych znaków, w tym znaki nowego wiersza, są zastępowane jednym pustym miejscem. Dlatego wynik działania echo $(ls)pojawia się w jednym wierszu.
Aby uzyskać zaawansowaną dyskusję na temat podziału słów, zobacz często zadawane pytania Grega .
Pomijanie podziału słów
Powłoka nie wykonuje dzielenia słów na ciągi w cudzysłowie. W ten sposób możesz ukryć dzielenie słów i zachować wieloliniowe wyjście za pomocą:
echo "$(ls)"
ls i wyjście wielowierszowe
Być może zauważyłeś, że lsczasami drukuje więcej niż jeden plik w linii:
$ ls
file1 file2 file3 file4 file5 file6
Jest to ustawienie domyślne, gdy dane wyjściowe są przesyłane lsdo terminala. Gdy dane wyjściowe nie idą bezpośrednio do terminala, lszmienia się domyślnie na jeden plik w linii:
$ echo "$(ls)"
file1
file2
file3
file4
file5
file6
To zachowanie jest udokumentowane w man ls.
Kolejna subtelność: zastępowanie poleceń i końcowe znaki nowej linii
$(...)jest podstawieniem polecenia, a powłoka usuwa końcowe znaki nowego wiersza z wyjścia podstawienia polecenia . Zwykle nie jest to zauważalne, ponieważ domyślnie echododaje jeden nowy wiersz na końcu danych wyjściowych. Tak więc, jeśli stracisz jedną nową linię od końca $(...)i zyskasz jedną z echo, nie ma zmiany. Jeśli jednak dane wyjściowe polecenia kończą się co najmniej 2 znakami nowej linii, a echododaje tylko jeden znak z powrotem, w wynikach brakuje jednego lub więcej znaków nowej linii. Jako przykład możemy użyć printfdo generowania końcowych znaków nowego wiersza. Zauważ, że oba poniższe polecenia, pomimo różnej liczby znaków nowej linii, dają takie same dane wyjściowe z jednej pustej linii:
$ echo "$(printf "\n")"
$ echo "$(printf "\n\n\n\n\n")"
$
To zachowanie jest udokumentowane w man bash.
Kolejna niespodzianka: dwukrotne rozwinięcie nazwy ścieżki
Utwórzmy trzy pliki:
$ touch 'file?' file1 file2
Zaobserwować różnicę między ls file?i echo $(ls file?):
$ ls file?
file? file1 file2
$ echo $(ls file?)
file? file1 file2 file1 file2
W przypadku echo $(ls file?)glob pliku file?jest dwukrotnie rozszerzany , powodując, że nazwy plików file1i file2pojawia się dwukrotnie na wyjściu. Jest tak, ponieważ, jak wskazuje Jeffiekins, interpretacja ścieżki jest wykonywana najpierw przez powłokę przed lsuruchomieniem, a następnie ponownie przed echouruchomieniem.
Drugie rozszerzenie nazwy ścieżki można pominąć, jeśli użyjemy podwójnych cudzysłowów:
$ echo "$(ls file?)"
file?
file1
file2