Як відобразити числа у зворотному порядку за допомогою seq (1)?


36

Я переглядаю номери в різному порядку. Я в змозі відображати їх у порядку збільшення, навіть з такими кроками, як:

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

Я також в змозі відображати їх у зворотному порядку, ні безперервно, ні кроково.

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

Немає виводу для вищезазначених команд.

Мої деталі оболонки:

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

Дайте мені знати, як я міг би відображати числа у порядку зменшення?


10
Для майбутніх читачів seqце абсолютно нестандартний інструмент, і немає гарантії того, що будь-які дві реалізації будуть однаковими. Якщо вам потрібно написати цикл, який повторює зворотній бік чисел у bash, використовуйте for ((i=$max;i>=0;i--)) …тощо.
kojiro

Відповіді:



20

Взагалі, ви не хочете користуватися seq, він не портативний (навіть серед стандартних середовищ Linux). Якщо ви використовуєте ksh, zsh або bash4 +, ви можете використовувати розширення дужок:

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

1
Це коротко і швидко, але я перебуваю на старшій версії bash.
mtk

20
Солодка відповідь, але є деяка іронія, коли ти вказуєш, що seqце нестандартно, а потім використовувати розширення дужок лише для bash-4. ;)
якийro

@kojiro - Ніякого аргументу, щоб бути чесним ;-) Моя головна стурбованість - це не те, чи існує команда (це може бути, а може, і не має значення залежно від того, чи розповсюджується сценарій / тощо), а чи виконується команда так, як очікується Автор. Підтяжка розширення bash4 майже гарантована (якщо вона працює, то вона працює, як ви очікували), тоді як seqні.
Кріс Даун

1
Чому він не портативний? У вас є джерела чи докази? Я зацікавлений.
Бенуа Дюффез

15

Інший спосіб у чистому bash, ksh або zsh:

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

Чистий спосіб POSIX sh:

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

1
forДругим виразом має бути тест, а третім - крок.
манатура

7

Тепер стандартні POSIX:

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

(Цікаво, з mawk(і в меншій мірі gawk, а) набагато швидше , ніж GNU seqдля i = 10000000замість i = 10)

Або

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

(було б ефективніше лише при невеликій кількості ітерацій, особливо з bash)

Або

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

(що підтримує номери будь-якого розміру, але зауважте, що після певної кількості цифр (цифри, що перевищують 10 70 принаймні в локалі POSIX), рядки будуть обернені косою рисою)


1
У GNU bc ви можете уникнути обгортання рядків, встановивши BC_LINE_LENGTH=0в оточенні. В інших реалізаціях такої удачі немає.
Жиль "ТАК - перестань бути злим"

1
Навіщо використовувати аргументи позиції, а не петлю навколо s=$s,$iабо виклик echo -n/ echo \c/ printf?
Жил "ТАК - перестань бути злим"

2

Ви можете скасувати замовлення, використовуючи tac(котик у зворотному порядку). Навіть якщо seqв різних системах поводиться по-різному, я думаю, що наступне має бути максимально портативним:

$ 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

Спробуйте:

   seq [OPTION]... FIRST INCREMENT LAST

Приклад:

$ seq 10 -1 1

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.