-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathshell-array
More file actions
173 lines (161 loc) · 4.91 KB
/
Copy pathshell-array
File metadata and controls
173 lines (161 loc) · 4.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#!/bin/sh -efu
### This file is covered by the GNU General Public License,
### which should be included with the file LICENSE.
### All copyright information are listed in the COPYING.
if [ -z "${__included_shell_array-}" ]; then
__included_shell_array=1
. shell-error
### Arrays implemented on plain shell variables.
###
### An array named 'myarr' is the element count variable 'myarr'
### plus the zero-based element variables 'myarr0', 'myarr1', and
### so on. Elements are dense and may hold arbitrary values,
### including spaces, quotes and newlines.
###
### Note on naming: an array name must not be a prefix of another
### array name immediately followed by a digit (arrays 'x' and 'x1'
### collide on the slot variable 'x1'), and both the array name and
### the caller's out-variables must not use the internal
### '__shell_array_' prefix.
###
### Usage errors (bad arguments, invalid names or indices, out of
### bounds) are fatal.
### Check that $1 may be used as a variable name.
__shell_array_name()
{
case "$1" in
''|[!a-zA-Z_]*|*[!a-zA-Z0-9_]*)
fatal "Invalid variable name: $1"
;;
esac
}
### Check that $1 is a non-negative decimal integer without leading
### zeros (so it is safe in arithmetic expressions).
__shell_array_index()
{
case "$1" in
0|[1-9]|[1-9][0-9]*)
: ;;
*)
fatal "Invalid array index: $1"
;;
esac
}
### Assign $2 to the variable named $1.
### $1 must have been checked by __shell_array_name; the value is
### assigned in a quoted context, so arbitrary values are safe.
__shell_array_set()
{
eval "$1=\"\$2\""
}
### Append a value to the end of an array.
### Usage: shell_array_append array value
shell_array_append()
{
[ "$#" -eq 2 ] ||
fatal "Usage: shell_array_append array value"
local __shell_array_n
__shell_array_name "$1"
eval "__shell_array_n=\${$1:-0}"
__shell_array_set "$1$__shell_array_n" "$2"
eval "$1=$(( __shell_array_n + 1 ))"
return 0
}
### Set a value in an array at the given index, growing the array
### with empty elements as needed; with no index the value is
### appended.
### Usage: shell_array_set array value [index]
shell_array_set()
{
[ "$#" -eq 2 ] || [ "$#" -eq 3 ] ||
fatal "Usage: shell_array_set array value [index]"
local __shell_array_sz __shell_array_i
__shell_array_name "$1"
eval "__shell_array_sz=\${$1:-0}"
__shell_array_i="${3:-$__shell_array_sz}"
__shell_array_index "$__shell_array_i"
while [ "$__shell_array_sz" -lt "$__shell_array_i" ]; do
__shell_array_set "$1$__shell_array_sz" ''
__shell_array_sz=$(( __shell_array_sz + 1 ))
done
__shell_array_set "$1$__shell_array_i" "$2"
if [ "$__shell_array_sz" -eq "$__shell_array_i" ]; then
__shell_array_sz=$(( __shell_array_i + 1 ))
fi
eval "$1=$__shell_array_sz"
return 0
}
### Store the element at index in the caller's variable.
### Usage: shell_array_get array index variable
shell_array_get()
{
[ "$#" -eq 3 ] ||
fatal "Usage: shell_array_get array index variable"
local __shell_array_n
__shell_array_name "$1"
__shell_array_name "$3"
__shell_array_index "$2"
eval "__shell_array_n=\${$1:-0}"
[ "$2" -lt "$__shell_array_n" ] ||
fatal "Index $2 out of bounds (size $__shell_array_n)"
eval "$3=\"\${$1$2-}\""
return 0
}
### Remove the last element of the array; with a second argument its
### value is stored in the caller's variable.
### Usage: shell_array_pop array [variable]
shell_array_pop()
{
[ "$#" -eq 1 ] || [ "$#" -eq 2 ] ||
fatal "Usage: shell_array_pop array [variable]"
local __shell_array_n
__shell_array_name "$1"
eval "__shell_array_n=\${$1:-0}"
[ "$__shell_array_n" -gt 0 ] ||
fatal "Array $1 is empty"
__shell_array_n=$(( __shell_array_n - 1 ))
if [ "$#" -eq 2 ]; then
__shell_array_name "$2"
eval "$2=\${$1$__shell_array_n-}"
fi
eval "$1=$__shell_array_n"
return 0
}
### Destroy the whole array, or remove the element at index
### compacting the elements that follow.
### Usage: shell_array_unset array [index]
shell_array_unset()
{
[ "$#" -eq 1 ] || [ "$#" -eq 2 ] ||
fatal "Usage: shell_array_unset array [index]"
local __shell_array_n
__shell_array_name "$1"
eval "__shell_array_n=\${$1:-0}"
[ "$__shell_array_n" -gt 0 ] ||
fatal "Array $1 is empty"
if [ "$#" -eq 1 ]; then
local __shell_array_i
__shell_array_i=0
while [ "$__shell_array_i" -lt "$__shell_array_n" ]; do
unset "$1$__shell_array_i"
__shell_array_i=$(( __shell_array_i + 1 ))
done
unset "$1"
return 0
fi
local __shell_array_i __shell_array_v
__shell_array_i=$2
__shell_array_index "$__shell_array_i"
[ "$__shell_array_i" -lt "$__shell_array_n" ] ||
fatal "Index $2 out of bounds (size $__shell_array_n)"
__shell_array_i=$(( __shell_array_i + 1 ))
while [ "$__shell_array_i" -lt "$__shell_array_n" ]; do
eval "__shell_array_v=\${$1$__shell_array_i-}"
__shell_array_set "$1$(( __shell_array_i - 1 ))" "$__shell_array_v"
__shell_array_i=$(( __shell_array_i + 1 ))
done
unset "$1$(( __shell_array_n - 1 ))"
eval "$1=$(( __shell_array_n - 1 ))"
return 0
}
fi #__included_shell_array