Not very difficult:
#!/bin/bash
hr=(00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23)
for i in ${hr[@]}; do
echo ${hr[i]}
done
But:
user@userver:$ ./stat.sh
00
01
02
03
04
05
06
07
./stat.sh: string 7: 08: value too great for base (error token is "08")
Bash thinks that leading zero means octal number system. What to do?
CodePudding user response:
I think your fundamental problem is that you're using each element of the array to index the array itself.
If you want to just print out the array elements, you should be outputting ${i}
rather than ${hr[i]}
. The latter is useless in your current code since element zero is 00
, element one is 01
, and so on.
On the chance that this is a simplified example and you do want to reference a different array based on the content of this one, you have a couple of options:
- Realise that the value of an integer and the presentation of it are two distinct things. In other words, use
0, 1, 2, ...
but something likeprintf "d" $i
if you need to output it (noting this is only ouputting the value in the first array, not the one you're looking up things in). - Exclusively use strings and a string-based associative array rather than an integer-based one, see
typeset -A
for detail.
CodePudding user response:
When you iterate with:
for i in ${hr[@]}; do
It is iterating the values of the array witch are:
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23
But when within the loop it has:
echo ${hr[i]}
it is using i
as the index of the hr
array.
In Bash, an index within the brackets of an array like [i]
is an arithmetic context. It means while the value of i=08
the leading 0
within the arithmetic context causes the number to be treated as an octal number, and 8
is an invalid octal number.
If you wanted to iterate your array indexes to process its values by index, then you'd start the loop as:
for i in "${!hr[@]}"; do
This one will perfectly work as it iterates the index into the variable i
:
#!/usr/bin/env bash
declare -a hr=(00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23)
for i in "${!hr[@]}"; do
printf '%s\n' "${hr[i]}"
done
Now if all you want is iterate the values of the hr
array, just do this way:
#!/usr/bin/env bash
declare -a hr=(00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23)
for e in "${hr[@]}"; do
printf '%s\n' "$e"
done
No need to index the array within the loop, since the elements are already expanded into e
.
CodePudding user response:
You can specify it's 10-based :
echo ${hr[10#$i]}
CodePudding user response:
one way is .... `$a=(echo {0..0}{1..99}) $ echo ${a[@]} echo 01 02 03 04 05 06 07 08 09 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099
CodePudding user response:
Use brace expansion (ranges, repetition).
To create an array:
hours=({00..23})
Loop through it:
for i in "${hours[@]}"; do
echo "$i"
done
Or loop through a brace expansion:
for i in {00..23}; do
echo "$i"
done
Regarding your error, it's because in bash arithmetic, all numbers with leading zeroes are treated as octals, and 08 and 09 are invalid octal numbers. All indexed array subscripts are evaluated as arithmetic expressions. You can fix the problem by using the notation base#number
to specify a number system. So for base 10: 10#09
, or for i=09
, 10#$i
. The variable must be prefixed with $
, 10#i
does not work.
You should be printing your array like this anyway:
Loop through elements:
for i in "${hr[@]}"; do
echo "$i"
done
Loop through indexes:
for i in "${!hr[@]}"; do
echo "index is $i"
echo "element is ${hr[i]}"
done
If you need to do arithmetic on the hours, or any zero padded number, you will lose the zero padding. You can print it again with printf: printf %.2d "$num"
, where 2
is the minimum width.