Как создать последовательность с ведущими нулями, используя расширение скобки

46

Когда я использую следующее, я получаю ожидаемый результат:

$ echo {8..10}
8 9 10

Как я могу использовать это расширение скобки простым способом, чтобы получить следующий результат?

$ echo {8..10}
08 09 10

Я теперь, что это может быть получено с помощью seq(не пытался), но это не то, что я ищу.

Полезной информацией может быть то, что я ограничен этой версией bash. (Если у вас есть zshрешение, но нет bashрешения, пожалуйста, поделитесь)

$ bash -version
GNU bash, version 3.2.51(1)-release (x86_64-suse-linux-gnu)
Бернхард
источник
Некоторые подсказки, чтобы сделать это в bash 3, я нашел здесь: mywiki.wooledge.org/BashFAQ/018 Однако описанный там подход не удобен.
Бернхард
stackoverflow.com/questions/8789729/zero-padding-in-bash
Сиро Сантилли 事件 改造 中心 法轮功 六四 事件

Ответы:

70

Префикс первого числа с, 0чтобы каждый термин имел одинаковую ширину.

$ echo {08..10}
08 09 10

Из раздела man-страницы bash по расширению Brace:

Поставляемые целые числа могут иметь префикс 0, чтобы каждый член имел одинаковую ширину. Когда x или y начинается с нуля, оболочка пытается заставить все сгенерированные термины содержать одинаковое количество цифр, при необходимости дополняя нулями.

Также обратите внимание, что вы можете использовать seqэту -wопцию для выравнивания ширины, добавляя начальные нули:

$ seq -w 8 10
08
09
10

$ seq -s " " -w 8 10
08 09 10

Если вы хотите больше контроля, вы можете даже указать формат стиля printf:

$ seq -s " " -f %02g 8 10
08 09 10
кендырь
источник
8
Однако, после того, как мы узнали о echo {08..10}решении, оно появилось только для bash версии 4 и выше.
Бернхард
Это делает меня немного неудобным, что Bash делает это. Для набора утилит (например perl) ведущий ноль указывает восьмеричное число. Я предполагаю, что не часто вы хотите последовательность восьмеричных чисел ...
kurtm
5
Следует отметить, что вы также можете использовать префикс перед цифрами seqс помощью -wпереключателя следующим образом: seq -w 003производит числа 001, 002 и 003.
slm
@kurtm не беспокойся о ведущих нулях. Это может быть больно, когда что-то пытается разобрать число. На самом деле это полезно при создании последовательности имен файлов, foo_00001.someextensionгде почти все контексты сортировки обеспечивают нормальное упорядочение.
Стефан Гурихон
9

если вы используете printf

printf "%.2d " {8..10} 

это заставит быть 2 символа и добавит начальный 0. В случае, если вам нужно 3 цифры, вы можете изменить на «% .3d».

BitsOfNix
источник
Спасибо за Ваш ответ. Я знаю о printfрешении, но на самом деле это не делает это проще. Я надеюсь, что есть какой-то скрытый трюк, который делает работу :)
Бернхард
Это единственный ответ, который кажется достаточно универсальным, чтобы справиться с любыми обстоятельствами происхождения номера для заполнения. Я использую счетчик, чтобы просмотреть файлы. Это решение printf безошибочно дополняет нуля, в то время как все остальные, по-видимому, сосредоточены на генерации чисел с нулями, а не на нулях существующих чисел.
могучий
7

Используйте диапазон, который начинается с постоянной цифры и удалите эту цифру:

echo \ {108..110} | sed 's/ 1//g'

или без использования внешней команды:

a=({108..110}); echo "${a[@]#1}"

Для использования в цикле for:

for x in {108..110}; do
  x=${x#1}
  
done

хотя для этого случая цикл while будет более понятным и работает в любой оболочке POSIX:

x=8
while [ $x -le 10 ]; do
  n=$((100+x)); n=${n#1}
  
  x=$((x+1))
done
Жиль "ТАК - перестань быть злым"
источник
Я принял этот ответ выше других ответов, потому что он удовлетворяет запросу на Bash 3.x. Тем более, что я все forравно нуждался в петле.
Бернхард
6

У меня та же версия bash исходного постера ( GNU bash, version 3.2.51(1)-release), и {08..12}она не работает для меня, но следующее работает:

for i in 0{8..9} {10..12}; do echo $i; done
08
09
10
11
12

Это немного более утомительно, но работает на OP версии Bash (и более поздние версии, я бы предположил).

Григорий Дулин
источник
Я не думал об этом решении (хотя в моем случае я также хочу набрать 0001 1000, но ваш принцип работает, конечно.
Бернхард
1

Для справки, я думаю, что автоматическая фиксированная ширина происходит только с последней версией bash:

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

$ echo test{00..05}
test0 test1 test2 test3 test4 test5
Бенджамин Гудэйкр
источник
-3
for i in $(seq -s " " -f %0${zeros}g $ini $fin); do ....;done

нули, ini и fin - переменные, так что легко, вы пишете только те нули, которые вы говорите в «нулях», чтобы ini к fin без проблем;)

miniminiyo
источник