Dlaczego jest echo {1,2,3}rozwinięty do 1 2 3, co jest oczekiwanym zachowaniem, podczas gdy echo [[:digit:]]zwraca , podczas [[:digit:]]gdy spodziewałem się, że wydrukuje wszystkie cyfry od 0do 9?
Ponieważ są to dwie różne rzeczy. {1,2,3}Jest przykładem ekspansji usztywniającym . {1,2,3}Konstrukt jest rozszerzony przez powłokę , zanim echojeszcze widzi. Możesz zobaczyć, co się stanie, jeśli użyjesz set -x:
$ set-x
$ echo {1,2,3}+ echo 123123
Jak widać, polecenie echo {1,2,3}jest rozwinięte do:
echo 123
Jednak [[:digit:]]jest klasa znaków POSIX . Gdy go podasz echo, powłoka najpierw przetwarza go, ale tym razem jest przetwarzana jako glob powłoki . działa tak samo jak podczas uruchamiania, echo *który wydrukuje wszystkie pliki w bieżącym katalogu. Ale [[:digit:]]jest globem powłoki, który będzie pasował do dowolnej cyfry. Teraz, bash, jeśli glob powłoki nie pasuje do niczego, zostanie rozwinięty do siebie:
Jeśli glob pasuje do czegoś, co zostanie wydrukowane:
$ echo /e*c
+ echo /etc
/etc
W obu przypadkach echopo prostu wypisuje wszystko, co powłoka nakazuje wydrukować, ale w drugim przypadku, ponieważ glob pasuje do czegoś ( /etc), poleca się wydrukować coś.
Ponieważ nie masz żadnych plików ani katalogów, których nazwa składa się z dokładnie jednej cyfry (co [[:digit:]]by się zgadzało), glob rozszerza się do siebie i otrzymujesz:
$ echo [[:digit:]][[:digit:]]
Teraz spróbuj utworzyć plik o nazwie 5i uruchomić to samo polecenie:
$ echo [[:digit:]]5
A jeśli istnieje więcej niż jeden pasujący plik:
$ touch 15
$ echo [[:digit:]]15
Jest to (w pewnym sensie) udokumentowane w man bashobjaśnieniu nullglobopcji, które wyłączają to zachowanie:
nullglob
Ifset, bash allows patterns which match no files (see
PathnameExpansion above) to expand to a null string,
rather than themselves.
Zobacz także, shopt -s failglobaby uzyskać bardziej przydatne zachowanie podobne do współczesnych powłok, takich jak zshlub fish.
Stéphane Chazelas,
Zgadzam się ze Stéphane, użyj failglob. nullglobmoże powodować nieoczekiwane problemy, np. podczas wklejania adresu URL, który ma ?.
Kevin
1
Jasne, wspomniałem tylko, nullglobaby pokazać, że wzór jest interpretowany przez powłokę jako glob.
terdon
14
{1,2,3}jest rozwinięciem nawiasów , rozszerza się na wyrazy wymienione bez względu na ich znaczenie.
[...]to grupa znaków, używana w rozszerzaniu nazw plików (lub symbolach wieloznacznych lub globalnych) podobnie jak gwiazdka *i znak zapytania ?. Pasuje do każdego pojedynczego znaku na liście lub znaków należących do nazwanych grup, takich jak [:digit:]te, które są na liście. Domyślnym zachowaniem większości powłok jest pozostawienie znaku wieloznacznego bez zmian, jeśli nie ma pasujących plików.
(Zauważ, że tak naprawdę nie można przekształcić symbolu wieloznacznego / wzoru w zestaw pasujących łańcuchów. Gwiazdka może pasować do dowolnego łańcucha o dowolnej długości, więc rozwinięcie dowolnego zawierającego go wzoru spowodowałoby nieskończoną listę łańcuchów.)
Więc:
$ bash -c 'echo [[:digit:]]'# bash leaves it as-is[[:digit:]]
$ zsh -c 'echo [[:digit:]]'# zsh by default complains if no match
zsh:1: no matches found:[[:digit:]]
$ touch 13 d i g t
$ bash -c 'echo [[:digit:]]'# now there are two matches13# note that d, i, g and t do NOT match
Ale nadal:
$ bash -c 'echo {1,2,3}'123
Oba są rozszerzone przez powłokę , nie ma znaczenia, czy uruchomione polecenie to ls, echolub rm. Pamiętaj też, że jeśli którykolwiek z nich jest cytowany, nie zostaną one rozwinięte:
$ bash -c 'echo "[[:digit:]]"'# even though matching files still exist[[:digit:]]
$ bash -c 'echo "{1,2,3}"'{1,2,3}
dziękuję za twoją odpowiedź, jestem nowy w systemie Linux, więc pozwól, że zapytam cię, jak echo jest związane z plikami 1 3, jego funkcją jest wydrukowanie argumentów na standardowe wyjście, nie szukając plików według mojej wiedzy
AbdAllah Talaat
1
@AbdAllahTalaat, to nie ma nic wspólnego z echem. Powłoka (np. Bash) „rozszerzy się” [[:digit:]]przed przekazaniem jej echo, więc echonigdy nie widzi [[:digit:]], tylko widzi 1 3. Możesz to zobaczyć w działaniu poprzez uruchomienie, set -xktóre wypisze uruchomione polecenia (uruchom, set +xaby je ponownie wyłączyć).
terdon
@AbdAllahTalaat, echonie szuka plików, powłoka robi to przed uruchomieniem echo.
ilkkachu
Zwłaszcza, że myślę, że w DOS / Windows narzędzia rozszerzają symbole wieloznaczne, a nie powłokę. (Może się mylę)
ilkkachu
przepraszam chłopaki, przesunąłem poprawną odpowiedź na odpowiedź tedron, ponieważ jego komentarz zawierał znaczenie tego, że bash jest tym, czego praca nie odbija się echem ... jego odpowiedź również zawierała to znaczenie ... wszyscy pomogliście mi ... chciałbym móc poprawna odpowiedź na wszystkie twoje odpowiedzi i komentarze
AbdAllah Talaat
4
{1,2,3}(i np. {1..3}są rozszerzeniami nawiasów klamrowych . Są one interpretowane przez powłokę przed wykonaniem polecenia.
[[:digit:]]jest tokenem pasującym do wzorca , ale nie używasz go w lokalizacji z plikami pasującymi do tego wzorca. Jeśli użyjesz dopasowania wzorca, które nie ma dopasowań, rozwija się ono do siebie:
Odpowiedzi:
Ponieważ są to dwie różne rzeczy.
{1,2,3}
Jest przykładem ekspansji usztywniającym .{1,2,3}
Konstrukt jest rozszerzony przez powłokę , zanimecho
jeszcze widzi. Możesz zobaczyć, co się stanie, jeśli użyjeszset -x
:Jak widać, polecenie
echo {1,2,3}
jest rozwinięte do:Jednak
[[:digit:]]
jest klasa znaków POSIX . Gdy go podaszecho
, powłoka najpierw przetwarza go, ale tym razem jest przetwarzana jako glob powłoki . działa tak samo jak podczas uruchamiania,echo *
który wydrukuje wszystkie pliki w bieżącym katalogu. Ale[[:digit:]]
jest globem powłoki, który będzie pasował do dowolnej cyfry. Teraz, bash, jeśli glob powłoki nie pasuje do niczego, zostanie rozwinięty do siebie:Jeśli glob pasuje do czegoś, co zostanie wydrukowane:
W obu przypadkach
echo
po prostu wypisuje wszystko, co powłoka nakazuje wydrukować, ale w drugim przypadku, ponieważ glob pasuje do czegoś (/etc
), poleca się wydrukować coś.Ponieważ nie masz żadnych plików ani katalogów, których nazwa składa się z dokładnie jednej cyfry (co
[[:digit:]]
by się zgadzało), glob rozszerza się do siebie i otrzymujesz:Teraz spróbuj utworzyć plik o nazwie
5
i uruchomić to samo polecenie:A jeśli istnieje więcej niż jeden pasujący plik:
Jest to (w pewnym sensie) udokumentowane w
man bash
objaśnieniunullglob
opcji, które wyłączają to zachowanie:Jeśli ustawisz tę opcję:
źródło
shopt -s failglob
aby uzyskać bardziej przydatne zachowanie podobne do współczesnych powłok, takich jakzsh
lubfish
.failglob
.nullglob
może powodować nieoczekiwane problemy, np. podczas wklejania adresu URL, który ma?
.nullglob
aby pokazać, że wzór jest interpretowany przez powłokę jako glob.{1,2,3}
jest rozwinięciem nawiasów , rozszerza się na wyrazy wymienione bez względu na ich znaczenie.[...]
to grupa znaków, używana w rozszerzaniu nazw plików (lub symbolach wieloznacznych lub globalnych) podobnie jak gwiazdka*
i znak zapytania?
. Pasuje do każdego pojedynczego znaku na liście lub znaków należących do nazwanych grup, takich jak[:digit:]
te, które są na liście. Domyślnym zachowaniem większości powłok jest pozostawienie znaku wieloznacznego bez zmian, jeśli nie ma pasujących plików.(Zauważ, że tak naprawdę nie można przekształcić symbolu wieloznacznego / wzoru w zestaw pasujących łańcuchów. Gwiazdka może pasować do dowolnego łańcucha o dowolnej długości, więc rozwinięcie dowolnego zawierającego go wzoru spowodowałoby nieskończoną listę łańcuchów.)
Więc:
Ale nadal:
Oba są rozszerzone przez powłokę , nie ma znaczenia, czy uruchomione polecenie to
ls
,echo
lubrm
. Pamiętaj też, że jeśli którykolwiek z nich jest cytowany, nie zostaną one rozwinięte:źródło
[[:digit:]]
przed przekazaniem jejecho
, więcecho
nigdy nie widzi[[:digit:]]
, tylko widzi1 3
. Możesz to zobaczyć w działaniu poprzez uruchomienie,set -x
które wypisze uruchomione polecenia (uruchom,set +x
aby je ponownie wyłączyć).echo
nie szuka plików, powłoka robi to przed uruchomieniemecho
.{1,2,3}
(i np.{1..3}
są rozszerzeniami nawiasów klamrowych . Są one interpretowane przez powłokę przed wykonaniem polecenia.[[:digit:]]
jest tokenem pasującym do wzorca , ale nie używasz go w lokalizacji z plikami pasującymi do tego wzorca. Jeśli użyjesz dopasowania wzorca, które nie ma dopasowań, rozwija się ono do siebie:źródło