Różnica między {1,2,3} a {1..3}

17

Czy istnieje różnica między sekwencjami {1,2,3}a {1..3}?

Na przykład, jeśli mam jakieś pliki

file.1
file.2
file.3

i chcę catje razem Czy korzystanie z niego jest bezpieczne cat file.{1..3} > file?

Wiem, że cat file.*>filemoże to powodować problemy, ponieważ powłoka może czasami losowo rozszerzać pliki (myślę, że to zależy od i-węzłów, prawda?)

syss
źródło
1
usecat file.[123] >file
mikeserv
3
Kolejność rozszerzania file.*nie zależy od i-węzłów. Zawsze sortuje je leksykograficznie, co może zależeć od ustawień lokalizacji.
Barmar,
1
„zależy od i-węzłów” brzmi jak faza jednej z lepiej zbadanych scen „komputerowych” spraw przestępczych.
Alec Teal
1
@ Mikeserv, wydaje mi się, że go mam - to glob powłoki, więc rozwija się tylko do plików, które faktycznie istnieją, prawda? Vs. file.{1..3}który rozszerza się na wszystkie trzy, niezależnie od tego, czy istnieją.
Wildcard,
1
@Wildcard - racja, o ile istnieje co najmniej jeden. Jeśli nie, to wcale się nie rozwija, a catbłędy file.[123] not foundlub coś bardzo przydatnego.
mikeserv

Odpowiedzi:

18

{1..3}i {1,2,3}dają ten sam wynik, ale w inny sposób.

Ogólnie rzecz biorąc, {n1..n2}(który był pierwszy zsh, basha kshpóźniej skopiowany), gdzie n1i n2są liczbami całkowitymi, tworzą wszystkie liczby między n1i n2. Choć {x,y,z}produkują trzy znaki x, ya z.

W twoim przypadku możesz bezpiecznie używać cat file.{1..3} > file

Teraz, w przypadku cat file.*>file, użyłeś globowania powłoki , który tworzy wszystkie nazwy plików zaczynające się od, file.a wynik zostanie posortowany na podstawie kolejności sortowania w bieżących ustawieniach narodowych.

Nadal jesteś bezpieczny, ale już nie, gdy masz więcej niż 10 plików. {1..10}da ci 1 2 3 4 5 6 7 8 9 10. Podczas korzystania z globowania dostaniesz1 10 2 3 4 5 6 7 8 9

Cuonglm
źródło
8

Różnica polega na tym, że jedna jest listą, a drugą sekwencją. {1,2,3}rozszerza się do trzech konkretnych elementów 1, 2oraz 3. {1..3}rozwija się do listy liczb od jednego do trzech. W tym konkretnym przypadku są one takie same i możesz użyć jednego z dwóch. file.*rozwinie się do wszystkich plików i katalogów w bieżącym katalogu, którego nazwa zaczyna się od file.. Jeśli tylko masz file.1, to file.2i file.3to jest równoważne z pozostałymi dwoma.

Jeśli chodzi o powodowanie problemów, nie rozumiem dlaczego. Być może myślisz

$ cat file.* > file.txt
cat: file.txt: input file is output file

To jednak zupełnie inna kwestia. Jedynym innym problemem, jaki mogę wymyślić, jest to, że twoja powłoka może nie wyświetlać plików we właściwej kolejności. Na przykład:

$ touch file1 file11 file2
$ echo file*
file1 file11 file2

Aby rozwiązać ten problem, możesz użyć zshzamiast bash(zobacz tutaj, aby uzyskać szczegółowe informacje):

% echo f*(n)
file1 file2 file11

Zasadniczo trzy podejścia nie są takie same. To zależy od tego, co chcesz zrobić. W tych przypadkach, gdy trzy zwracają to samo wyjście, wtedy, tak, możesz użyć dowolnego z nich. To nie robi różnicy. Wszystkie te rozszerzenia są wykonywane przez powłokę i zdarzają się, zanim zostaną przekazane do dowolnego polecenia, które ich używa.

terdon
źródło
czy nie byłoby problemu, *gdybym miał więcej lub równych 10 plików, jeśli zależę od właściwej kolejności?
syss
1
@syss no. Byłoby to problemem, gdybyś miał więcej niż ARG_MAXpliki, ale tak będzie znacznie więcej niż 10.
terdon
1
@terdon Pytał, czy pojawią się w kolejności numerycznej (tzn. nie „1, 10, 2”), a nie czy przepełnią tablicę argumentów.
Random832,
3
@terdon Myślę, że @syss ma rację, że wynik cat *nie jest dobrze zdefiniowany. Wynik zależy od powłoki i środowiska. Zobacz komentarz Sebastiana .
Marco,
Czy dodanie nie .txtrozwiąże problemu file.*?
Ismael Miguel
6

Są takie same, ale zależy od zainstalowanej wersji bash, jeśli są one dostępne.

Z tej strony:

{xxx,yyy,zzz,...} probably in all bash versions

{a..z} introduced in bash 3

{<START>..<END>..<INCR>} new in bash 4
Cristi
źródło