├── LICENSE ├── README.md ├── liblist.sh ├── liblist_unsafe.sh └── tests ├── test.sh └── test_unsafe.sh /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017-2018 Thomas "Ventto" Venriès 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | POSIX Shell List 2 | ================ 3 | 4 | [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/Ventto/libshlist/blob/master/LICENSE) 5 | 6 | *"This is a POSIX Shell list implementation."* 7 | 8 | ## Perks 9 | 10 | * [x] **No requirement**: Shell POSIX-compliant 11 | * [x] **Lightweight**: ~100 lines 12 | * [x] **Both**: Safe and unsafe (passing argument by reference) 13 | 14 | # Installation 15 | 16 | * Download it: 17 | 18 | ```bash 19 | $ wget https://raw.githubusercontent.com/Ventto/libshlist/master/liblist.sh 20 | ``` 21 | 22 | * Source the library for including the functions into your Shell script: 23 | 24 | ```bash 25 | . liblist.sh (or) 26 | . liblist_unsafe.sh 27 | ``` 28 | 29 | Each function is independent. So you can copy some functions into your script 30 | without sourcing. 31 | 32 | # Functions 33 | 34 | The whole function documentation is in the following library scripts: 35 | 36 | * `liblist.sh` requires variable assignation 37 | * `liblist_unsafe.sh` uses the `eval` Shell builtin for passing argument 38 | by reference 39 | 40 | The following list enumerates all available functions: 41 | 42 | ``` 43 | SAFE | UNSAFE 44 | ____________________________________|_______________________________ 45 | list ... | list ... 46 | list_back | list_back 47 | list_contains | list_contains 48 | list_count | list_count 49 | list_empty | list_empty 50 | list_erase | list_erase 51 | list_erase_from | list_erase_from 52 | list_erase_range | list_erase_range 53 | list_eraseat | list_eraseat 54 | list_extract | list_extract 55 | list_front | list_front 56 | list_get | list_get 57 | list_indexof | list_indexof 58 | list_insert | list_insert 59 | list_maps | list_maps 60 | list_pop_back | list_pop_back 61 | list_pop_front | list_pop_front 62 | list_push_back | list_push_back 63 | list_push_front | list_push_front 64 | list_remove | list_remove 65 | list_replace | list_replace 66 | list_reverse | list_reverse 67 | list_set | list_set 68 | list_size | list_size 69 | list_sort | list_sort 70 | list_sort_reverse | list_sort_reverse 71 | ``` 72 | 73 | # Examples 74 | 75 | * Safe: 76 | 77 | ```bash 78 | lst="$(list 'C' 'A' 'B')" 79 | lst="$(list_sort "$lst")" # { A, B, C } 80 | 81 | index="$(list_indexof 'B' "$lst")" # Empty String if not found 82 | printf '"B": found at %d\n' "$index" 83 | ``` 84 | 85 | * Unsafe: 86 | 87 | ```bash 88 | lst="$(list 'C' 'A' 'B')" 89 | list_sort lst # { A, B, C } 90 | 91 | index="$(list_indexof lst 'B')" # Empty String if not found 92 | printf '"B" found at %d\n' "$index" 93 | ``` 94 | 95 | See also scripts in `tests/` as examples. 96 | -------------------------------------------------------------------------------- /liblist.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # The MIT License (MIT) 4 | # 5 | # Copyright (c) 2017-2018 Thomas "Ventto" Venriès 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | # this software and associated documentation files (the "Software"), to deal in 9 | # the Software without restriction, including without limitation the rights to 10 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | # the Software, and to permit persons to whom the Software is furnished to do so, 12 | # subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | ## 25 | # @brief Return a list from argument strings 26 | # @usage list ... 27 | # @print The created list 28 | # 29 | list () { 30 | for e; do [ -n "$e" ] && echo "$e"; done 31 | } 32 | 33 | ## 34 | # @brief Prints the number of elements in the list 35 | # @usage list_size 36 | # @print The size of the list as positive integer 37 | # 38 | list_size () { 39 | if [ -z "$1" ]; then echo '0'; else echo "$@" | wc -l; fi 40 | } 41 | 42 | ## 43 | # @brief Returns whether the list is empty(1) or not(0) 44 | # @usage list_empty 45 | # @return The exit code of the command 46 | # 47 | list_empty () { 48 | test -z "$1" 49 | } 50 | 51 | ## 52 | # @brief Adds a new element at the beginning of the list 53 | # @usage list_push_front 54 | # @print The list result 55 | # 56 | list_push_front () { 57 | test "$#" -ne 2 && return 1 58 | if [ "$2" = '' ]; then echo "$1"; else printf '%s\n%s' "$1" "$2"; fi 59 | } 60 | 61 | ## 62 | # @brief Adds a new element at the end of the list 63 | # @usage list_push_back 64 | # @print The list result 65 | # 66 | list_push_back () { 67 | test "$#" -ne 2 && return 1 68 | if [ "$2" = '' ]; then echo "$1"; else printf '%s\n%s' "$2" "$1"; fi 69 | } 70 | 71 | ## 72 | # @brief Inserts new elements in the list before a specified position 73 | # @usage list_insert 74 | # @print The list result 75 | # 76 | list_insert () { 77 | test "$#" -ne 3 && return 1 78 | i="$2"; [ "$i" != '$' ] && i=$((i+1)); echo "$3" | sed "${i}i${1}" 79 | } 80 | 81 | ## 82 | # @brief Modifies an element from the list at a specified position 83 | # @usage list_set 84 | # @print The list result 85 | # 86 | list_set () { 87 | test "$#" -ne 3 && return 1 88 | i="$2"; i=$((i+1)); echo "$3" | sed -e "${i}s/.*/$1/" 89 | } 90 | 91 | ## 92 | # @brief Extracts a range of elements from the list between two specified 93 | # positions 94 | # @usage list_extract 95 | # @print The list result 96 | # 97 | list_extract () { 98 | test "$#" -ne 3 && return 1 99 | i="$1"; j="$2"; i=$((i+1)); j=$((j+1)); echo "$3" | sed -n "${i},${j}p" 100 | } 101 | 102 | ## 103 | # @brief Replaces all elements from the list with a specified element 104 | # @usage list_replace 105 | # @print The list result 106 | # 107 | list_replace () { 108 | test "$#" -ne 3 && return 1; echo "$3" | sed -e "s/^$1$/$2/g" 109 | } 110 | 111 | ## 112 | # @brief Prints the element at a specified position 113 | # @usage list_get 114 | # @print The element found 115 | # 116 | list_get () { 117 | test "$#" -ne 2 && return 1; i="$1"; i=$((i+1)); echo "$2" | sed -n "${i}p" 118 | } 119 | 120 | ## 121 | # @brief Prints the head of the list 122 | # @usage list_front 123 | # @print The element found 124 | # 125 | list_front () { 126 | test "$#" -ne 1 && return 1; echo "$@" | sed -n '1p' 127 | } 128 | 129 | ## 130 | # @brief Prints the queue of the list 131 | # @usage list_back 132 | # @print The element found 133 | # 134 | list_back () { 135 | test "$#" -ne 1 && return 1; echo "$@" | sed -n '$p' 136 | } 137 | 138 | ## 139 | # @brief Removes the first-hit element from a list 140 | # @usage list_erase 141 | # @print The list result 142 | # 143 | list_erase () { 144 | test "$#" -ne 2 && return 1; echo "$2" | sed -e "0,/^$1$/ s///" -e '/^$/d' 145 | } 146 | 147 | ## 148 | # @brief Removes a range of elements from a list between two specified 149 | # positions 150 | # @usage list_erase_range 151 | # @print The list result 152 | # 153 | list_erase_range () { 154 | test "$#" -ne 3 && return 1 155 | i="$1"; j="$2"; i=$((i+1)); j=$((j+1)); echo "$3" | sed "${i},${j}d" 156 | } 157 | 158 | ## 159 | # @brief Removes all elements from a specified position 160 | # @usage list_erase_from 161 | # @print The list result 162 | # 163 | list_erase_from () { 164 | test "$#" -ne 2 && return 1; i="$1"; i=$((i+1)); echo "$2" | sed "${i},\$d" 165 | } 166 | 167 | ## 168 | # @brief Removes the element at a specified position 169 | # @usage list_eraseat 170 | # @print The list result 171 | # 172 | list_eraseat () { 173 | test "$#" -ne 2 && return 1; i="$1"; i=$((i+1)); echo "$2" | sed "${i}d" 174 | } 175 | 176 | ## 177 | # @brief Removes all the elements from the list, which are equal to given 178 | # element 179 | # @usage list_remove 180 | # @print The list result 181 | # 182 | list_remove () { 183 | test "$#" -ne 2 && return 1; echo "$2" | sed -e "/^$1$/d" 184 | } 185 | 186 | ## 187 | # @brief Removes the first element of the list 188 | # @usage list_pop_front 189 | # @print The list result 190 | # 191 | list_pop_front () { 192 | test "$#" -ne 1 && return 1; echo "$1" | sed '1d' 193 | } 194 | 195 | ## 196 | # @brief Removes the last element of the list 197 | # @usage list_pop_back 198 | # @print The list result 199 | # 200 | list_pop_back () { 201 | test "$#" -ne 1 && return 1; echo "$1" | sed '$d' 202 | } 203 | 204 | ## 205 | # @brief Prints the index of a specified element 206 | # @usage list_indexof 207 | # @print The index or empty string if the element is not found 208 | # 209 | list_indexof () { 210 | test "$#" -ne 2 && return 1; i=0 211 | for e in $2; do 212 | [ "$e" = "$1" ] && { echo "$i"; return 0; }; i=$((i+1)); 213 | done 214 | return 1 215 | } 216 | 217 | ## 218 | # @brief Returns whether the list contains a specified element(0) or not(1) 219 | # @usage list_contains 220 | # @return 0 or 1 221 | # 222 | list_contains () { 223 | test "$#" -ne 2 && return 1 224 | for e in $2; do [ "$e" = "$1" ] && return 0; done; return 1 225 | } 226 | 227 | ## 228 | # @brief Counts the number of a specified element in the list 229 | # @usage list_count 230 | # @print The number of elements as positive integer 231 | # 232 | list_count () { 233 | test "$#" -ne 2 && return 1 234 | i=0; for e in $2; do [ "$e" = "$1" ] && { i=$((i+1)); }; done; echo "$i" 235 | } 236 | 237 | ## 238 | # @brief Maps every element of the list 239 | # @usage list_maps 240 | # @print The list result 241 | # 242 | list_map () { 243 | test "$#" -ne 2 && return 1; for e in $2; do eval "$1 $e"; done 244 | } 245 | 246 | ## 247 | # @brief Reverses the list 248 | # @usage list_reverse 249 | # @print The list result 250 | # 251 | list_reverse() { 252 | test "$#" -ne 1 && return 1; echo "$1" | sed '1!x;H;1h;$!d;g' 253 | } 254 | 255 | ## 256 | # @brief Sorts the list 257 | # @usage list_sort 258 | # @print The list result 259 | # 260 | list_sort () { 261 | test "$#" -ne 1 && return 1; echo "$1" | sort -n 262 | } 263 | 264 | ## 265 | # @brief Sorts and reverses the sense of the list 266 | # @usage list_sort_reverse 267 | # @print The list result 268 | # 269 | list_sort_reverse () { 270 | test "$#" -ne 1 && return 1; echo "$1" | sort -nr 271 | } 272 | -------------------------------------------------------------------------------- /liblist_unsafe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # The MIT License (MIT) 4 | # 5 | # Copyright (c) 2017-2018 Thomas "Ventto" Venriès 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | # this software and associated documentation files (the "Software"), to deal in 9 | # the Software without restriction, including without limitation the rights to 10 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | # the Software, and to permit persons to whom the Software is furnished to do so, 12 | # subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | ## 25 | # @brief Prints a list from arguments 26 | # @usage list ... 27 | # @print The list result 28 | # 29 | list () { 30 | for e; do [ -n "$e" ] && echo "$e"; done 31 | } 32 | 33 | ## 34 | # @brief Prints the number of elements in the list 35 | # @usage list_size 36 | # @print The size of the list as positive integer 37 | # 38 | list_size () { 39 | test "$#" -ne 1 && { echo "0"; return; } 40 | eval "test -n \"\$$1\"" && { eval "echo \"\$$1\" | wc -l"; return; } 41 | echo '0' 42 | } 43 | 44 | ## 45 | # @brief Returns whether the list is empty(1) or not(0) 46 | # @usage list_empty 47 | # @return 0 or 1 48 | # 49 | list_empty () { 50 | eval "test -z \"\$$1\"" 51 | } 52 | 53 | ## 54 | # @brief Adds a new element at the beginning of the list 55 | # @usage list_push_front 56 | # @out Set the variable passed by reference 57 | # 58 | list_push_front () { 59 | test "$#" -ne 2 && return 1 60 | eval "test -n \"\$$1\"" || { eval "$1='$2'"; return; } 61 | eval "$1=\"\$(printf '%s\n%s' '$2' \"\$$1\")\""; 62 | } 63 | 64 | ## 65 | # @brief Adds a new element at the end of the list 66 | # @usage list_push_back 67 | # @out Set the variable passed by reference 68 | # 69 | list_push_back () { 70 | test "$#" -ne 2 && return 1 71 | eval "test -n \"\$$1\"" || { eval "$1='$2'"; return; } 72 | eval "$1=\"\$(printf '%s\n%s' \"\$$1\" '$2')\""; 73 | } 74 | 75 | ## 76 | # @brief Inserts new elements in the list before a specified position 77 | # @usage list_insert 78 | # @out Set the variable passed by reference 79 | # 80 | list_insert () { 81 | test "$#" -ne 3 && return 1; i="$3"; [ "$i" != '$' ] && i=$((i+1)) 82 | eval "$1=\"\$(echo \"\$$1\" | sed \"${i}i${2}\")\"" 83 | } 84 | 85 | ## 86 | # @brief Modifies an element from the list at a specified position 87 | # @usage list_set 88 | # @out Set the variable passed by reference 89 | # 90 | list_set () { 91 | test "$#" -ne 3 && return 1 92 | i="$3"; i=$((i+1)); eval "$1=\"\$(echo \"\$$1\" | sed \"${i}s/.*/$2/\")\"" 93 | } 94 | 95 | ## 96 | # @brief Extracts a range of elements from the list between two specified 97 | # positions 98 | # @usage list_extract 99 | # @out Set the variable passed by reference 100 | # 101 | list_extract () { 102 | test "$#" -ne 3 && return 1; i="$2"; j="$3"; i=$((i+1)); j=$((j+1)) 103 | eval "$1=\"\$(echo \"\$$1\" | sed -n \"${i},${j}p\")\"" 104 | } 105 | 106 | ## 107 | # @brief Replaces all elements from the list with a specified element 108 | # @usage list_replace 109 | # @out Set the variable passed by reference 110 | # 111 | list_replace () { 112 | test "$#" -ne 3 && return 1 113 | eval "$1=\"\$(echo \"\$$1\" | sed -e \"s/^$2$/$3/g\")\"" 114 | } 115 | 116 | ## 117 | # @brief Prints the element at a specified position 118 | # @usage list_get 119 | # @print The element found 120 | # 121 | list_get () { 122 | test "$#" -ne 2 && return 1; i="$2"; i=$((i+1)); 123 | eval "echo \"\$$1\" | sed -n \"${i}p\"" 124 | } 125 | 126 | ## 127 | # @brief Prints the head of the list 128 | # @usage list_front 129 | # @print The element found 130 | # 131 | list_front () { 132 | test "$#" -ne 1 && return 1; eval "echo \"\$$1\" | sed -n '1p'" 133 | } 134 | 135 | ## 136 | # @brief Prints the queue of the list 137 | # @usage list_back 138 | # @print The element found 139 | # 140 | list_back () { 141 | test "$#" -ne 1 && return 1; eval "echo \"\$$1\" | sed -n '\$p'" 142 | } 143 | 144 | ## 145 | # @brief Removes the first-hit element from a list 146 | # @usage list_erase 147 | # @out Set the variable passed by reference 148 | # 149 | list_erase () { 150 | test "$#" -ne 2 && return 1 151 | eval "$1=\"\$(echo \"\$$1\" | sed -e \"0,/^$2$/ s///\" -e '/^$/d')\"" 152 | } 153 | 154 | ## 155 | # @brief Removes a range of elements from a list between two specified 156 | # positions 157 | # @usage list_erase_range 158 | # @out Set the variable passed by reference 159 | # 160 | list_erase_range () { 161 | test "$#" -ne 3 && return 1 162 | i="$2"; j="$3"; i=$((i+1)); j=$((j+1)); 163 | eval "$1=\"\$(echo \"\$$1\" | sed \"${i},${j}d\")\"" 164 | } 165 | 166 | ## 167 | # @brief Removes all elements from a specified position 168 | # @usage list_erase_from 169 | # @out Set the variable passed by reference 170 | # 171 | list_erase_from () { 172 | test "$#" -ne 2 && return 1 173 | i="$2"; i=$((i+1)); eval "$1=\"\$(echo \"\$$1\" | sed \"${i},\\\$d\")\"" 174 | } 175 | 176 | ## 177 | # @brief Removes the element at a specified position 178 | # @usage list_eraseat 179 | # @out Set the variable passed by reference 180 | # 181 | list_eraseat () { 182 | test "$#" -ne 2 && return 1 183 | i="$2"; i=$((i+1)); eval "$1=\"\$(echo \"\$$1\" | sed \"${i}d\")\"" 184 | } 185 | 186 | ## 187 | # @brief Removes all the elements from the list, which are equal to given 188 | # element 189 | # @usage list_remove 190 | # @out Set the variable passed by reference 191 | # 192 | list_remove () { 193 | test "$#" -ne 2 && return 1 194 | eval "$1=\"\$(echo \"\$$1\" | sed -e \"/^$2$/d\")\"" 195 | } 196 | 197 | ## 198 | # @brief Removes the first element of the list 199 | # @usage list_pop_front 200 | # @out Set the variable passed by reference 201 | # 202 | list_pop_front () { 203 | test "$#" -ne 1 && return 1; eval "$1=\"\$(echo \"\$$1\" | sed '1d')\"" 204 | } 205 | 206 | ## 207 | # @brief Removes the last element of the list 208 | # @usage list_pop_back 209 | # @out Set the variable passed by reference 210 | # 211 | list_pop_back () { 212 | test "$#" -ne 1 && return 1; eval "$1=\"\$(echo \"\$$1\" | sed '\$d')\"" 213 | } 214 | 215 | ## 216 | # @brief Prints the index of a specified element 217 | # @usage list_indexof 218 | # @print positive integer or -1 if not found 219 | # 220 | list_indexof () { 221 | test "$#" -ne 2 && return 1; i=0 222 | eval "for e in \$$1; do 223 | [ \"\$e\" = '$2' ] && { echo \"\$i\"; return 0; }; i=\$((i+1)); 224 | done" 225 | return 1 226 | } 227 | 228 | ## 229 | # @brief Returns whether the list contains a specified element(0) or not(1) 230 | # @usage list_contains 231 | # @return 0 or 1 232 | # 233 | list_contains () { 234 | test "$#" -ne 2 && return 1 235 | eval "for e in \$$1; do [ \"\$e\" = '$2' ] && return 0; done; return 1" 236 | } 237 | 238 | ## 239 | # @brief Prints the number of a specified element in the list 240 | # @usage list_count 241 | # @print The number of elements as positive integer 242 | # 243 | list_count () { 244 | test "$#" -ne 2 && { echo '0'; return; } 245 | eval "i=0; for e in \$$1; do [ \"\$e\" = '$2' ] && { i=\$((i+1)); };done;" 246 | echo "$i" 247 | } 248 | 249 | ## 250 | # @brief Maps every element of the list 251 | # @usage list_maps 252 | # @out Set the variable passed by reference 253 | # 254 | list_map () { 255 | test "$#" -ne 2 && return 1 256 | eval "$1=\"\$(for e in \$$1; do eval \"$2 \$e\"; done)\"" 257 | } 258 | 259 | ## 260 | # @brief Reverses the list 261 | # @usage list_reverse 262 | # @out Set the variable passed by reference 263 | # 264 | list_reverse() { 265 | test "$#" -ne 1 && return 1 266 | eval "$1=\"\$(echo \"\$$1\" | sed '1!x;H;1h;\$!d;g')\"" 267 | } 268 | 269 | ## 270 | # @brief Sorts the list 271 | # @usage list_sort 272 | # @out Set the variable passed by reference 273 | # 274 | list_sort () { 275 | test "$#" -ne 1 && return 1; eval "$1=\"\$(echo \"\$$1\" | sort -n)\"" 276 | } 277 | 278 | ## 279 | # @brief Sorts and reverses the sense of the list 280 | # @usage list_sort_reverse 281 | # @out Set the variable passed by reference 282 | # 283 | list_sort_reverse () { 284 | test "$#" -ne 1 && return 1; eval "$1=\"\$(echo \"\$$1\" | sort -nr)\"" 285 | } 286 | -------------------------------------------------------------------------------- /tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | . ./liblist.sh 4 | 5 | print_list () { 6 | echo '==========List============' 7 | printf "%s\n" "$1" 8 | echo '--------------------------' 9 | printf "Size: %s\t\n\n" "$(list_size "$1")" 10 | } 11 | 12 | Test_Delete () { 13 | lst="$(list '1' '12' '23' \ 14 | '33' '215' '-456' \ 15 | '1236' '1' '12' \ 16 | '3' '-3' '33' \ 17 | '1' '12' '-55' \ 18 | '123' '-1002' '-1' )" 19 | 20 | printf "TEST: Deletion\n\n" 21 | echo 'test: Initialization'; print_list "$lst" 22 | 23 | lst="$(list_remove '1' "$lst")" ; echo 'test:' ; print_list "$lst" 24 | lst="$(list_erase '33' "$lst")" ; echo 'test:' ; print_list "$lst" 25 | lst="$(list_eraseat '3' "$lst")" ; echo 'test:' ; print_list "$lst" 26 | lst="$(list_pop_front "$lst")" ; echo 'test:' ; print_list "$lst" 27 | lst="$(list_pop_back "$lst")" ; echo 'test:' ; print_list "$lst" 28 | lst="$(list_erase_from '8' "$lst")" ; echo 'test:' ; print_list "$lst" 29 | lst="$(list_erase_range '1' '2' "$lst")"; echo 'test:' ; print_list "$lst" 30 | lst="$(list_erase_range '0' '0' "$lst")"; echo 'test:' ; print_list "$lst" 31 | lst="$(list_extract '1' '3' "$lst")" ; echo 'test:' ; print_list "$lst" 32 | lst="$(list_extract '1' '30' "$lst")" ; echo 'test:' ; print_list "$lst" 33 | lst="$(list_extract '1' '0' "$lst")" ; echo 'test:' ; print_list "$lst" 34 | } 35 | 36 | Test_Addition () { 37 | lst= 38 | 39 | printf "TEST: Addition\n\n" 40 | echo 'test: Initialization'; print_list "$lst" 41 | 42 | lst="$(list_push_front '12' "$lst")" ; echo 'test:' ; print_list "$lst" 43 | lst="$(list_push_back '33' "$lst")" ; echo 'test:' ; print_list "$lst" 44 | lst="$(list_push_front '1' "$lst")" ; echo 'test:' ; print_list "$lst" 45 | lst="$(list_insert '23' '2' "$lst")" ; echo 'test:' ; print_list "$lst" 46 | lst="$(list_push_back '215' "$lst")" ; echo 'test:' ; print_list "$lst" 47 | } 48 | 49 | inc () { i="$1"; i=$((i+1)); echo "${i}"; } 50 | Test_Set() { 51 | lst="$(list '1' '12' '23' \ 52 | '33' '215' '-456' \ 53 | '1236' '1' '12' )" 54 | 55 | printf "TEST: Set\n\n" 56 | echo 'test: Initialization'; print_list "$lst" 57 | 58 | lst="$(list_reverse "$lst")" ; echo 'test:' ; print_list "$lst" 59 | lst="$(list_sort "$lst")" ; echo 'test:' ; print_list "$lst" 60 | lst="$(list_sort_reverse "$lst")" ; echo 'test:' ; print_list "$lst" 61 | lst="$(list_map inc "$lst")" ; echo 'test:' ; print_list "$lst" 62 | lst="$(list_replace '2' '999' "$lst")" ; echo 'test:' ; print_list "$lst" 63 | lst="$(list_set '999' '3' "$lst")" ; echo 'test:' ; print_list "$lst" 64 | lst="$(list_set '999' '6' "$lst")" ; echo 'test:' ; print_list "$lst" 65 | } 66 | 67 | Test_Get() { 68 | lst="$(list '1' '12' '23' \ 69 | '33' '215' '-456' \ 70 | '1236' '1' '12' )" 71 | 72 | printf "TEST: Get\n\n" 73 | echo 'test: Initialization'; print_list "$lst" 74 | 75 | printf 'test: elt=' ; list_front "$lst" 76 | printf 'test: elt=' ; list_back "$lst" 77 | printf 'test: elt=' ; list_get '2' "$lst" 78 | printf 'test: index=' ; list_indexof '1' "$lst" | grep -E '^[0-9]+$' || echo 79 | printf 'test: index=' ; list_indexof '-456' "$lst" | grep -E '^[0-9]+$' || echo 80 | printf 'test: contains='; list_contains '1236' "$lst" && echo 'yes' || echo 'no' 81 | printf 'test: contains='; list_contains '999' "$lst" && echo 'yes' || echo 'no' 82 | printf 'test: count=' ; list_count '1' "$lst" 83 | printf 'test: count=' ; list_count '215' "$lst" 84 | printf 'test: empty=' ; list_empty "$lst" && echo 'yes' || echo 'no' 85 | } 86 | -------------------------------------------------------------------------------- /tests/test_unsafe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | . ./liblist_unsafe.sh 4 | 5 | print_list () { 6 | echo '==========List============' 7 | eval "printf \"%s\\n\" \"\$$1\"" 8 | echo '--------------------------' 9 | eval "printf \"Size: %s\t\n\n\" \"\$(list_size $1)\"" 10 | } 11 | 12 | Test_Delete () { 13 | lst="$(list '1' '12' '23' \ 14 | '33' '215' '-456' \ 15 | '1236' '1' '12' \ 16 | '3' '-3' '33' \ 17 | '1' '12' '-55' \ 18 | '123' '-1002' '-1' )" 19 | 20 | printf "TEST: Deletion\n\n" 21 | echo 'test: Initialization'; print_list lst 22 | 23 | list_remove lst '1' ; echo 'test:' ; print_list lst 24 | list_erase lst '33' ; echo 'test:' ; print_list lst 25 | list_eraseat lst 3 ; echo 'test:' ; print_list lst 26 | list_pop_front lst ; echo 'test:' ; print_list lst 27 | list_pop_back lst ; echo 'test:' ; print_list lst 28 | list_erase_from lst 8 ; echo 'test:' ; print_list lst 29 | list_erase_range lst 1 2 ; echo 'test:' ; print_list lst 30 | list_erase_range lst 0 0 ; echo 'test:' ; print_list lst 31 | list_extract lst 1 3 ; echo 'test:' ; print_list lst 32 | list_extract lst 1 30 ; echo 'test:' ; print_list lst 33 | list_extract lst 1 0 ; echo 'test:' ; print_list lst 34 | } 35 | 36 | Test_Addition () { 37 | lst= 38 | 39 | printf "TEST: Addition\n\n" 40 | echo 'test: Initialization'; print_list lst 41 | 42 | list_push_front lst '12' ; echo 'test:' ; print_list lst 43 | list_push_back lst '33' ; echo 'test:' ; print_list lst 44 | list_push_front lst '1' ; echo 'test:' ; print_list lst 45 | list_insert lst '23' 2 ; echo 'test:' ; print_list lst 46 | list_push_back lst '215' ; echo 'test:' ; print_list lst 47 | } 48 | 49 | inc () { i="$1"; i=$((i+1)); echo "${i}"; } 50 | Test_Set() { 51 | lst="$(list '1' '12' '23' \ 52 | '33' '215' '-456' \ 53 | '1236' '1' '12' )" 54 | 55 | printf "TEST: Set\n\n" 56 | echo 'test: Initialization'; print_list lst 57 | 58 | list_reverse lst ; echo 'test:' ; print_list lst 59 | list_sort lst ; echo 'test:' ; print_list lst 60 | list_sort_reverse lst ; echo 'test:' ; print_list lst 61 | list_map lst inc ; echo 'test:' ; print_list lst 62 | list_replace lst '2' '999' ; echo 'test:' ; print_list lst 63 | list_set lst '999' 3 ; echo 'test:' ; print_list lst 64 | list_set lst '999' 6 ; echo 'test:' ; print_list lst 65 | } 66 | 67 | Test_Get() { 68 | lst="$(list '1' '12' '23' \ 69 | '33' '215' '-456' \ 70 | '1236' '1' '12' )" 71 | 72 | printf "TEST: Set\n\n" 73 | echo 'test: Initialization'; print_list lst 74 | 75 | printf 'test: elt=' ; list_front lst 76 | printf 'test: elt=' ; list_back lst 77 | printf 'test: elt=' ; list_get lst 2 78 | printf 'test: index=' ; list_indexof lst '1' | grep -E '^[0-9]+$' || echo 79 | printf 'test: index=' ; list_indexof lst '-456' | grep -E '^[0-9]+$' || echo 80 | printf 'test: contains='; list_contains lst '1236' && echo 'yes' || echo 'no' 81 | printf 'test: contains='; list_contains lst '2' && echo 'yes' || echo 'no' 82 | printf 'test: count=' ; list_count lst '1' 83 | printf 'test: count=' ; list_count lst '215' 84 | printf 'test: empty=' ; list_empty lst && echo 'yes' || echo 'no' 85 | } 86 | 87 | Test_Void() { 88 | lst="$(list '' '' '')" 89 | 90 | printf "TEST: Void\n\n" 91 | echo 'test: Initialization'; print_list lst 92 | 93 | printf 'test (void): empty=' ; list_empty lst && echo 'yes' || echo 'no' 94 | printf 'test (void): size=' ; list_size lst 95 | 96 | list_reverse lst ; echo 'test:' ; print_list lst 97 | list_sort lst ; echo 'test:' ; print_list lst 98 | list_sort_reverse lst ; echo 'test:' ; print_list lst 99 | list_replace lst '2' '999' ; echo 'test:' ; print_list lst 100 | list_set lst '999' 3 ; echo 'test:' ; print_list lst 101 | list_set lst '999' 6 ; echo 'test:' ; print_list lst 102 | list_map lst inc ; echo 'test:' ; print_list lst 103 | list_remove lst '1' ; echo 'test:' ; print_list lst 104 | list_erase lst '33' ; echo 'test:' ; print_list lst 105 | list_eraseat lst 3 ; echo 'test:' ; print_list lst 106 | list_pop_front lst ; echo 'test:' ; print_list lst 107 | list_pop_back lst ; echo 'test:' ; print_list lst 108 | list_erase_from lst 8 ; echo 'test:' ; print_list lst 109 | list_erase_range lst 1 2 ; echo 'test:' ; print_list lst 110 | list_erase_range lst 0 0 ; echo 'test:' ; print_list lst 111 | list_extract lst 1 3 ; echo 'test:' ; print_list lst 112 | list_extract lst 1 30 ; echo 'test:' ; print_list lst 113 | list_extract lst 1 0 ; echo 'test:' ; print_list lst 114 | list_push_front lst '2' ; echo 'test:' ; print_list lst 115 | list_push_back lst '4' ; echo 'test:' ; print_list lst 116 | list_push_front lst '1' ; echo 'test:' ; print_list lst 117 | list_insert lst '3' 2 ; echo 'test:' ; print_list lst 118 | list_push_back lst '5' ; echo 'test:' ; print_list lst 119 | } 120 | 121 | Test_BadArg() { 122 | lst="$1" 123 | printf "TEST: BadArg\n\n" 124 | echo 'test: Initialization'; print_list lst 125 | 126 | list_push_front lst ; echo 'test:' ; print_list lst 127 | list_push_front '' ; echo 'test:' ; print_list lst 128 | list_push_front ; echo 'test:' ; print_list lst 129 | 130 | list_push_back lst ; echo 'test:' ; print_list lst 131 | list_push_back '' ; echo 'test:' ; print_list lst 132 | list_push_back ; echo 'test:' ; print_list lst 133 | 134 | list_insert lst '' ; echo 'test:' ; print_list lst 135 | list_insert lst ; echo 'test:' ; print_list lst 136 | list_insert 2 ; echo 'test:' ; print_list lst 137 | 138 | list_reverse ; echo 'test:' ; print_list lst 139 | list_sort ; echo 'test:' ; print_list lst 140 | list_sort_reverse ; echo 'test:' ; print_list lst 141 | 142 | list_replace lst '2' ; echo 'test:' ; print_list lst 143 | list_replace lst ; echo 'test:' ; print_list lst 144 | list_replace ; echo 'test:' ; print_list lst 145 | 146 | list_set lst '999' ; echo 'test:' ; print_list lst 147 | list_set lst ; echo 'test:' ; print_list lst 148 | list_set ; echo 'test:' ; print_list lst 149 | 150 | list_map lst ; echo 'test:' ; print_list lst 151 | list_map inc ; echo 'test:' ; print_list lst 152 | list_map ; echo 'test:' ; print_list lst 153 | 154 | list_remove lst ; echo 'test:' ; print_list lst 155 | list_remove '1' ; echo 'test:' ; print_list lst 156 | list_remove ; echo 'test:' ; print_list lst 157 | 158 | list_erase lst ; echo 'test:' ; print_list lst 159 | list_erase '33' ; echo 'test:' ; print_list lst 160 | list_erase ; echo 'test:' ; print_list lst 161 | 162 | list_eraseat lst ; echo 'test:' ; print_list lst 163 | list_eraseat 3 ; echo 'test:' ; print_list lst 164 | list_eraseat ; echo 'test:' ; print_list lst 165 | 166 | list_pop_front ; echo 'test:' ; print_list lst 167 | list_pop_back ; echo 'test:' ; print_list lst 168 | 169 | list_erase_from lst ; echo 'test:' ; print_list lst 170 | list_erase_from 8 ; echo 'test:' ; print_list lst 171 | list_erase_from ; echo 'test:' ; print_list lst 172 | 173 | list_erase_range lst 0 ; echo 'test:' ; print_list lst 174 | list_erase_range lst ; echo 'test:' ; print_list lst 175 | list_erase_range ; echo 'test:' ; print_list lst 176 | 177 | list_extract 0 1 ; echo 'test:' ; print_list lst 178 | list_extract lst 1 ; echo 'test:' ; print_list lst 179 | list_extract lst ; echo 'test:' ; print_list lst 180 | list_extract ; echo 'test:' ; print_list lst 181 | 182 | printf 'test: elt=' ; list_front || echo 183 | printf 'test: elt=' ; list_back || echo 184 | 185 | printf 'test: elt=' ; list_get lst || echo 186 | printf 'test: elt=' ; list_get 2 || echo 187 | printf 'test: elt=' ; list_get || echo 188 | 189 | printf 'test: index=' ; list_indexof lst | grep -E '^[0-9]+$' || echo 190 | printf 'test: index=' ; list_indexof '-456' | grep -E '^[0-9]+$' || echo 191 | printf 'test: index=' ; list_indexof | grep -E '^[0-9]+$' || echo 192 | 193 | printf 'test: contains='; list_contains lst && echo 'yes' || echo 'no' 194 | printf 'test: contains='; list_contains '2' && echo 'yes' || echo 'no' 195 | printf 'test: contains='; list_contains && echo 'yes' || echo 'no' 196 | 197 | printf 'test: count=' ; list_count lst 198 | printf 'test: count=' ; list_count '215' 199 | printf 'test: count=' ; list_count 200 | 201 | printf 'test: empty=' ; list_empty && echo 'yes' || echo 'no' 202 | } 203 | 204 | Test_VoidBadArg() { 205 | Test_BadArg "$(list '' '' '' '')" 206 | } 207 | 208 | Test_WithBadArg() { 209 | Test_BadArg "$(list 1 2 3)" 210 | } 211 | --------------------------------------------------------------------------------