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 IFS
oznacza 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 ls
czasami 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 ls
do terminala. Gdy dane wyjściowe nie idą bezpośrednio do terminala, ls
zmienia 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 echo
dodaje 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 echo
dodaje tylko jeden znak z powrotem, w wynikach brakuje jednego lub więcej znaków nowej linii. Jako przykład możemy użyć printf
do 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 file1
i file2
pojawia się dwukrotnie na wyjściu. Jest tak, ponieważ, jak wskazuje Jeffiekins, interpretacja ścieżki jest wykonywana najpierw przez powłokę przed ls
uruchomieniem, a następnie ponownie przed echo
uruchomieniem.
Drugie rozszerzenie nazwy ścieżki można pominąć, jeśli użyjemy podwójnych cudzysłowów:
$ echo "$(ls file?)"
file?
file1
file2