Jak wyświetlać liczby w odwrotnej kolejności za pomocą seq (1)?


36

Mam iterację liczb w różnej kolejności. Jestem w stanie wyświetlać je w kolejności rosnącej, nawet w krokach takich jak:

$ seq --separator="," 1 10
1,2,3,4,5,6,7,8,9,10
$ seq --separator="," 1 2 10
1,3,5,7,9

Jestem również w stanie wyświetlać je w odwrotnej kolejności, ani w sposób ciągły, ani krokowy.

$ seq --separator="," 10 1   
$ seq --separator="," 10 2 1

Brak danych wyjściowych dla powyższych poleceń.

Szczegóły mojej powłoki:

$ bash --version
GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.

Daj mi znać, jak będę mógł wyświetlać liczby w kolejności malejącej?


10
Dla przyszłych czytelników seqjest to całkowicie niestandardowe narzędzie i nie ma gwarancji, że dowolne dwa wdrożenia będą takie same. Jeśli potrzebujesz napisać pętlę, która będzie iterować wstecz po liczbach w bash, użyj for ((i=$max;i>=0;i--)) …lub tym podobnych.
kojiro

Odpowiedzi:



20

Zasadniczo nie chcesz używać seq, nie jest przenośny (nawet wśród standardowych środowisk Linux). Jeśli używasz ksh, zsh lub bash4 +, możesz użyć rozszerzenia nawiasów:

echo {10..1..2} | tr " " ,
10,8,6,4,2

1
To krótkie i szybkie, ale jestem na starszej wersji bash.
mtk

20
Słodka odpowiedź, ale ironia, gdy zauważysz, seqjest niestandardowa, a następnie użyj rozszerzenia nawiasów tylko dla bash-4. ;)
kojiro

@kojiro - Szczerze mówiąc, nie ma argumentu ;-) Moim głównym zmartwieniem nie jest to, czy polecenie istnieje (to może, ale nie musi mieć znaczenia, w zależności od tego, czy skrypt jest dystrybuowany / etc), ale czy polecenie wykonuje się zgodnie z oczekiwaniami Autor. Rozszerzenie nawiasów bash4 prawie ma taką gwarancję (jeśli działa, działa zgodnie z oczekiwaniami), podczas seqgdy nie.
Chris Down,

1
Dlaczego nie jest przenośny? Czy masz źródła lub dowody? Jestem zainteresowany.
Benoit Duffez,

15

Innym sposobem jest czysty bash, ksh lub zsh:

for ((i=10;i>0;i-=2)) ; do echo -n "$i," ; done

Czysty sposób POSIX:

i=10
while [ "$i" -gt 2 ]; do printf "$i,"; i=$((i-2)); done
echo "$i"

1
forDrugim wyrażeniem powinien być test, a trzeci krok.
manatwork

7

Teraz standardowe POSIX:

awk 'BEGIN{for (i = 10; i > 0; i -= 2) print i}' | paste -sd , -

(co ciekawe, z mawk(oraz w mniejszym stopniu gawkrównież) dużo szybciej niż GNU seqdla i = 10000000zamiast i = 10)

Lub

i=10; set --
while [ "$i" -gt 0 ]; do
  set -- "$@" "$i"
  i=$(($i - 2))
done
IFS=,
echo "$*"

(byłby bardziej wydajny przy małej liczbie iteracji, szczególnie z bash)

Lub

echo 'for(i=10;i>0;i-=2) i' | bc | paste -sd , -

(który obsługuje liczby dowolnej wielkości, ale należy pamiętać, że po przekroczeniu pewnej liczby cyfr ( co najmniej liczby większe niż 10 70 w ustawieniach regionalnych POSIX), linie byłyby zawijane ukośnikami odwrotnymi)


1
W GNU bc można uniknąć zawijania linii przez ustawienie BC_LINE_LENGTH=0w środowisku. Brak szczęścia w przypadku innych wdrożeń.
Gilles „SO- przestań być zły”

1
Po co używać argumentów pozycyjnych zamiast zapętlać s=$s,$ilub wywoływać echo -n/ echo \c/ printf?
Gilles „SO- przestań być zły”

2

Możesz odwrócić kolejność za pomocą tac(cat in reverse). Nawet jeśli seqpowinny zachowywać się inaczej w różnych systemach, myślę, że następujące elementy powinny być tak przenośne, jak to możliwe:

$ seq 1 10 | tr '\012' ',' | sed 's/,$//'; echo
1,2,3,4,5,6,7,8,9,10
$ seq 1 10 | tac | tr '\012' ',' | sed 's/,$//'; echo
10,9,8,7,6,5,4,3,2,1
$

2

Spróbuj z:

   seq [OPTION]... FIRST INCREMENT LAST

Przykład:

Sekw. 10–1 1

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.