Wie kann man mit seq (1) Zahlen in umgekehrter Reihenfolge anzeigen?


36

Ich habe über Zahlen in verschiedener Reihenfolge iteriert. Ich kann sie in aufsteigender Reihenfolge anzeigen, auch mit Schritten wie:

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

Ich kann sie auch in umgekehrter Reihenfolge anzeigen, weder fortlaufend noch schrittweise.

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

Keine Ausgabe für obige Befehle.

Meine Shell-Details:

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

Lassen Sie mich wissen, wie ich die Zahlen in absteigender Reihenfolge anzeigen kann?


10
Für zukünftige Leser seqist es ein völlig nicht standardisiertes Tool und es gibt keine Garantie dafür, dass zwei Implementierungen gleich sind. Wenn Sie eine Schleife , die wiederholt sich rückwärts über Zahlen in Bash, Gebrauch schreiben müssen for ((i=$max;i>=0;i--)) …oder dergleichen.
Kojiro

Antworten:


50

Verwenden Sie ein negatives Inkrement

seq -s, 10 -2 1
10,8,6,4,2

20

Im Allgemeinen möchten Sie es nicht verwenden seq, es ist nicht portabel (selbst in Standard-Linux-Umgebungen). Wenn Sie ksh, zsh oder bash4 + verwenden, können Sie die geschweifte Klammer verwenden:

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

1
Das ist kurz und schnell, aber ich bin auf einer älteren Bash-Version.
MTK

20
Süße Antwort, aber es gibt ein bisschen Ironie, wenn Sie darauf hinweisen, dass dies seqnicht der Standard ist und dann die reine Bash-4-Klammer-Erweiterung verwenden. ;)
Kojiro

@kojiro - Kein Argument, um ehrlich zu sein ;-) Mein Hauptanliegen ist nicht, ob der Befehl vorhanden ist (das kann oder nicht, je nachdem, ob das Skript verteilt wird / etc), sondern ob der Befehl wie erwartet ausgeführt wird der Autor. Die Klammererweiterung von bash4 hat beinahe diese Garantie (wenn es funktioniert, funktioniert es wie erwartet), während seqdies nicht der Fall ist.
Chris Down

1
Warum ist es nicht tragbar? Haben Sie Quellen oder Beweise? Ich bin interessiert.
Benoit Duffez

15

Ein anderer Weg in pure bash, ksh oder zsh:

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

Ein reiner POSIX-Weg:

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

1
forDer zweite Ausdruck sollte der Test und der dritte der Schritt sein.
Manatwork

7

Jetzt Standard POSIX diejenigen:

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

(interessanterweise mit mawk(und in geringerem Maß gawkauch) viel schneller als GNU seqfür i = 10000000statt i = 10)

Oder

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

(wäre nur mit wenigen Iterationen effizienter, insbesondere mit bash)

Oder

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

(Dies würde Zahlen jeder Größe unterstützen, aber beachten Sie, dass nach einer bestimmten Anzahl von Ziffern (Zahlen größer als 10 bis 70 im POSIX-Gebietsschema) Zeilen mit Backslashes umbrochen werden.)


1
In GNU bc können Sie den Zeilenumbruch vermeiden, indem Sie BC_LINE_LENGTH=0in der Umgebung einstellen . Kein Glück bei anderen Implementierungen.
Gilles 'SO- hör auf böse zu sein'

1
Warum die Positions Argumente verwenden , anstatt Schleife um s=$s,$ioder Anruf echo -n/ echo \c/ printf?
Gilles 'SO- hör auf böse zu sein'

2

Sie können die Reihenfolge mit tac(Katze in umgekehrter Reihenfolge) umkehren. Auch wenn seqsich auf verschiedenen Systemen etwas anders verhalten sollte, sollte meines Erachtens Folgendes so portabel wie möglich sein:

$ 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

Versuche es mit:

   seq [OPTION]... FIRST INCREMENT LAST

Beispiel:

$ seq 10 -1 1

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.