Как нулевое заполнение последовательности целых чисел в bash, чтобы все имели одинаковую ширину?
Мне нужно закодировать некоторые значения,
for i in $(seq $first $last)
do
does something here
done
Для $first
и $last
, мне нужно, чтобы она имела фиксированную длину 5. Итак, если входной файл 1
, мне нужно добавить нули впереди, чтобы он стал 00001
. Например, он работает до 99999
, но длина должна быть 5.
Например: 00002
, 00042
, 00212
, 012312
и т.д.
Любая идея о том, как я могу это сделать?
Ответы
Ответ 1
В вашем конкретном случае, хотя, вероятно, проще всего использовать флаг -f
для seq
, чтобы заставить его форматировать числа, когда он выводит список. Например:
for i in $(seq -f "%05g" 10 15)
do
echo $i
done
выдаст следующий результат:
00010
00011
00012
00013
00014
00015
В общем случае bash
имеет printf
как встроенный, поэтому вы можете выводить вывод с нулями следующим образом:
$ i=99
$ printf "%05d\n" $i
00099
Вы можете использовать флаг -v
для сохранения вывода в другой переменной:
$ i=99
$ printf -v j "%05d" $i
$ echo $j
00099
Обратите внимание, что printf
поддерживает немного другой формат seq
, поэтому вам нужно использовать %05d
вместо %05g
.
Ответ 2
Легче еще вы можете сделать
for i in {00001..99999}; do
echo $i
done
Ответ 3
Если конец последовательности имеет максимальную длину отступов (например, если вы хотите, чтобы 5 цифр и команда были "seq 1 10000" ), чем вы можете использовать флаг "-w" для seq - он добавляет саму себя.
seq -w 1 10
изготовлять
01
02
03
04
05
06
07
08
09
10
Ответ 4
используйте printf с "% 05d", например.
printf "%05d" 1
Ответ 5
Очень просто использовать printf
[jaypal:~/Temp] printf "%05d\n" 1
00001
[jaypal:~/Temp] printf "%05d\n" 2
00002
Ответ 6
Используйте awk следующим образом:
awk -v start=1 -v end=10 'BEGIN{for (i=start; i<=end; i++) printf("%05d\n", i)}'
ВЫВОД:
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
Update:
В качестве чистой альтернативы bash вы можете сделать это, чтобы получить тот же вывод:
for i in {1..10}
do
printf "%05d\n" $i
done
Таким образом, вы можете избежать использования внешней программы seq
, которая НЕ доступна для всех ароматов * nix.
Ответ 7
Я выкладываю вывод с большим количеством цифр (нулей), чем мне нужно, тогда используйте хвост, чтобы использовать только количество цифр, которые я ищу. Обратите внимание, что вы должны использовать "6" в хвосте, чтобы получить последние пять цифр:)
for i in $(seq 1 10)
do
RESULT=$(echo 00000$i | tail -c 6)
echo $RESULT
done
Ответ 8
Если вы хотите N цифр, добавьте 10 ^ N и удалите первую цифру.
for (( num=100; num<=105; num++ ))
do
echo ${num:1:3}
done
Вывод:
01
02
03
04
05
Ответ 9
Это будет работать также:
for i in {0..9}{0..9}{0..9}{0..9}
do
echo "$i"
done
Ответ 10
Другой путь:
zeroos="000"
echo
for num in {99..105};do
echo ${zeroos:${#num}:${#zeroos}}${num}
done
Так что простая функция для преобразования любого числа будет:
function leading_zero(){
local num=$1
local zeroos=00000
echo ${zeroos:${#num}:${#zeroos}}${num}
}
Ответ 11
1.) Создайте последовательность чисел 'seq' от 1 до 1000 и зафиксируйте ширину '-w' (ширина определяется длиной конечного числа, в данном случае 4 цифры на 1000).
2.) Кроме того, выберите, какие номера вы хотите, используя "sed -n" (в этом случае мы выбираем номера 1-100).
3.) "эхо" каждого номера. Числа хранятся в переменной "i", доступ к которой осуществляется с помощью "$".
Плюсы: этот код довольно чистый.
Минусы: 'seq' не свойственен всем системам Linux (насколько я понимаю)
for i in 'seq -w 1 1000 | sed -n '1,100p'';
do
echo $i;
done
Ответ 12
Если вы просто добавляете числа с нулями для достижения фиксированной длины, просто добавьте ближайшее кратное 10, например. для 2 цифр добавьте 10 ^ 2, затем удалите первую 1 перед отображением вывода.
Это решение работает для заполнения/форматирования отдельных чисел любой длины или целой последовательности чисел с использованием цикла for.
# Padding 0s zeros:
# Pure bash without externals eg. awk, sed, seq, head, tail etc.
# works with echo, no need for printf
pad=100000 ;# 5 digit fixed
for i in {0..99999}; do ((j=pad+i))
echo ${j#?}
done
Протестировано на Mac OSX 10.6.8, Bash ver 3.2.48
Ответ 13
Один из способов без использования внешнего процесса - это манипулирование строками, в общем случае это будет выглядеть так:
#start value
CNT=1
for [whatever iterative loop, seq, cat, find...];do
# number of 0s is at least the amount of decimals needed, simple concatenation
TEMP="000000$CNT"
# for example 6 digits zero padded, get the last 6 character of the string
echo ${TEMP:(-6)}
# increment, if the for loop does not provide the number directly
TEMP=$(( TEMP + 1 ))
done
Это хорошо работает и в WSL, где разветвление - очень тяжелая операция. У меня был список 110000 файлов, использование printf "%06d" $NUM
заняло более 1 минуты, решение, приведенное выше, заняло около 1 секунды.