135
You can access the array indices using ${!array[@]} and the length of the array using ${#array[@]}, e.g. :
#!/bin/bash
array=( item1 item2 item3 )
for index in ${!array[@]}; do
echo $index/${#array[@]}
done
Note that since bash arrays are zero indexed, you will actually get :
0/3
1/3
2/3
If you want the count to run from 1 you can replace $index by $...
116
As of bash 4.2, you can just use a negative index ${myarray[-1]} to get the last element. You can do the same thing for the second-last, and so on; in Bash:
If the subscript used to reference an element of an indexed array
evaluates to a number less than zero, it is interpreted as relative to
one greater than the maximum index of the array, so negative ...
answered Apr 27 '15 at 4:41
Michael Homer
63.4k1212 gold badges178178 silver badges206206 bronze badges
112
To add an element to the beginning of an array use.
arr=("new_element" "${arr[@]}")
Generally, you would do.
arr=("new_element1" "new_element2" "..." "new_elementN" "${arr[@]}")
To add an element to the end of an array use.
arr=( "${arr[@]}" "new_element" )
Or instead
arr+=( "new_element" )
Generally, you would do.
arr=( "${arr[@]}" "new_element1"...
83
Just use array syntax on the assignment and quote your variable:
array=("${array[@]:1}") #removed the 1st element
Edit according to question in comment. For $@ you can use it like this:
set -- "${@:2}" #removed the 1st parameter
73
When you use ./scriptname.sh it executes with /bin/bash as in the first line with #!. But when you use sh scriptname.sh it executes sh, not bash.
The sh shell has no syntax to create arrays, but Bash has the syntax you used.
60
/bin/sh is hardly ever a Bourne shell on any systems nowadays (even Solaris which was one of the last major system to include it has now switched to a POSIX sh for its /bin/sh in Solaris 11). /bin/sh was the Thompson shell in the early 70s. The Bourne shell replaced it in Unix V7 in 1979.
/bin/sh has been the Bourne shell for many years thereafter (or the ...
answered Jun 17 '14 at 9:55
Stéphane Chazelas
405k7171 gold badges795795 silver badges12071207 bronze badges
54
Just use:
mkdir -p -- "${array1[@]}"
That will also create intermediary directory components if need be so your array can also be shortened to only include the leaf directories:
array1=(
/apache/bin
/apache/conf
/apache/lib
/www/html
/www/cgi-bin
/www/ftp
)
Which you could also write:
array1=(
/apache/{bin,conf,lib}
/www/{html,cgi-bin,...
answered Nov 5 '19 at 6:41
Stéphane Chazelas
405k7171 gold badges795795 silver badges12071207 bronze badges
53
Modern bash (v4.1 or better)
You can read the last element at index -1:
$ a=(a b c d e f)
$ echo ${a[-1]}
f
Support for accessing numerically-indexed arrays from the end using negative indexes started with bash version 4.1-alpha.
Older bash (v4.0 or earlier)
You must get the array length from ${#a[@]} and then subtract one to get the last element:
$ ...
41
You can use the same format as for any other array. To extract the 2nd and 3rd elements from $@, you would do:
echo "${@:1:2}"
- -
| |----> slice length
|------> slice starting index
40
You can get the list of "keys" for the associative array like so:
$ echo "${!astr[@]}"
elemB elemA
You can iterate over the "keys" like so:
for i in "${!astr[@]}"
do
echo "key : $i"
echo "value: ${astr[$i]}"
done
Example
$ for i in "${!astr[@]}"; do echo "key : $i"; echo "value: ${astr[$i]}"; done
key : elemB
value: 199
key : elemA
value: 123
...
39
Virtually all shell arrays (Bourne, csh, tcsh, fish, rc, es, yash) start at 1. ksh is the only exception that I know (bash just copied ksh).
Most interpreted languages at the time (early 90s): awk, tcl at least, and tools typically used from the shell (cut -f1-3, head -n 3, sort -k1,3, cal 1 2015, comm -1) start at 1. sed, ed, vi number their lines from 1...
...
answered Dec 30 '15 at 21:04
Stéphane Chazelas
405k7171 gold badges795795 silver badges12071207 bronze badges
32
The syntax
delete array
is not in current versions in POSIX, but it is supported by virtually all existing implementations (including the original awk, GNU, mawk, and BusyBox). It will be added in a future version of POSIX (see defect 0000544).
An alternate way to clear all array elements, which is both portable and standard-compliant, and which is an ...
answered Aug 2 '14 at 0:40
Gilles 'SO- stop being evil'
669k162162 gold badges13941394 silver badges18961896 bronze badges
27
Using jq :
$ cat json
[
{
"item1": "value1",
"item2": "value2",
"sub items": [
{
"subitem": "subvalue"
}
]
},
{
"item1": "value1_2",
"item2": "value2_2",
"sub items_2": [
{
"subitem_2": "subvalue_2"
}
]
}
]
CODE:
arr=( $(jq -r '.[].item2' json) )
printf '%s\n' "${arr[@]}"
...
25
Little late, but I don't see the ideal sh answer here so I'll chime in. If you don't need subscripting, then sh effectively does support arrays. It just supports them as space separated strings. You can print the entire contents of them, "push" to them, or iterate through them just fine.
Here's a bit of sample code:
NAMES=""
NAMES="${NAMES} MYNAME"
NAMES="$...
25
This is an instance of pattern replacement in shell parameter expansion: ${parameter/pattern/replacement} expands ${parameter}, replacing the first instance of pattern with replacement. In the context of a pattern of this kind, # is special: it anchors the pattern to the start of the parameter. The end result of all this is to expand all the values in the ...
answered Oct 3 '18 at 13:30
Stephen Kitt
280k3434 gold badges687687 silver badges773773 bronze badges
22
The difference is subtle; "$*" creates one argument, while "$@" will expand into separate arguments, so:
LIST=(1 2 3)
for i in "${LIST[@]}"; do
echo "example.$i"
done
will deal with the list (print it) as multiple variables
but
LIST=(1 2 3)
for i in "${LIST[*]}"; do
echo "example.$i"
done
will ...
22
I think you're asking two different things there.
Is there a way to make bash print this info without the loop?
Yes, but they are not as good as just using the loop.
Is there a cleaner way to get/print only the key=value portion of the output?
Yes, the for loop. It has the advantages that it doesn't require external programs, is straightforward, and ...
21
You cannot pass two arguments with single option using getopts.
I recommend the following alternatives:
Put quotes around multiple arguments
In this case getopts will treat them as one argument, but you will be able to split it later on. You can even put all arguments in the array at once:
#!/bin/bash
while getopts ":hr:l:" opt; do
case $opt in
...
21
unset removes an element. It doesn't renumber the remaining elements.
We can use declare -p to see exactly what happens to numbers:
$ unset "numbers[i]"
$ declare -p numbers
declare -a numbers=([0]="53" [1]="8" [2]="12" [3]="9" [5]="69" [6]="8" [7]="7" [8]="1")
Observe the numbers no longer has an element 4.
Another example
Observe:
$ a=()
$ a[1]="...
20
Unconventional approach (all not pure bash):
if all elements in an array are just one characters (like in the question) you can use rev:
echo "${array[@]}" | rev
otherwise:
printf '%s\n' "${array[@]}" | tac | tr '\n' ' '; echo
and if you can use zsh:
echo ${(Oa)array}
20
Another unconventional approach:
#!/bin/bash
array=(1 2 3 4 5 6 7)
f() { array=("${BASH_ARGV[@]}"); }
shopt -s extdebug
f "${array[@]}"
shopt -u extdebug
echo "${array[@]}"
Output:
7 6 5 4 3 2 1
If extdebug is enabled, array BASH_ARGV contains in a function all positional parameters in reverse order.
20
To answer the question in the title, you can "shift" an array with the substring/subarray notation. (shift itself works with just the positional parameters.)
$ a=(a b c d e)
$ a=("${a[@]:1}")
$ echo "${a[@]}"
b c d e
Similarly, to 'pop' the last item off the array: a=("${a[@]:0:${#a[@]} - 1}" ) or unset "a[${#a[@]}-1]"
So if you wanted to, you could do ...
20
That's a feature of zsh inherited from csh/tcsh.
The $path array variable is tied to the $PATH scalar (string) variable. Any modification on one is reflected in the other.
In zsh (contrary to (t)csh), you can tie other variables beside $PATH with typeset -T. It's conventional, but not mandatory, to use an uppercase name for the colon-separated scalar and ...
answered Jul 25 '19 at 19:08
Stéphane Chazelas
405k7171 gold badges795795 silver badges12071207 bronze badges
19
Use a different kind of array: rather than an integer-indexed array, use an associative array, so the key (index) is what you will be checking for. bash-4.0 or later is required for this.
declare -A array1=(
[prova1]=1 [prova2]=1 [slack64]=1
)
a=slack64
[[ -n "${array1[$a]}" ]] && printf '%s is in array\n' "$a"
In the above we don't really ...
19
bash array assignment, reference, unsetting with negative index were only added in bash 4.3. With older version of bash, you can use expression in index array[${#array[@]-1}]
Another way, also work with older version of bash (bash 3.0 or better):
$ a=([a] [b] [c] [d] [e])
$ printf %s\\n "${a[@]:(-1)}"
[e]
or:
$ printf %s\\n "${a[@]: -1}"
[e]
Using ...
19
Generally calling:
var=value cmd
where cmd is a function is not portable.
With bash, that only works for scalar variables (and with x=(...) parsed as an array but assigned as a scalar) and there are a number of issues with scoping if you do that, with ksh93 and yash, it works but the variable definition remains afterwards. With mksh, you get a syntax ...
answered Dec 21 '17 at 20:01
Stéphane Chazelas
405k7171 gold badges795795 silver badges12071207 bronze badges
19
I have answered the question as written, and this code reverses the array. (Printing the elements in reverse order without reversing the array is just a for loop counting down from the last element to zero.) This is a standard "swap first and last" algorithm.
array=(1 2 3 4 5 6 7)
min=0
max=$(( ${#array[@]} -1 ))
while [[ min -lt max ]]
do
# Swap ...
18
All examples presented below work for general case where there's an arbitrary number of words on the line. The essential idea is the same everywhere - we have to read the file line by line and print the words in reverse. AWK facilitates this the best because it already has all the necessary tools for text processing done programmatically, and is most ...
answered Jan 10 '17 at 5:21
Sergiy Kolodyazhnyy
14.2k66 gold badges3939 silver badges8181 bronze badges
17
comm(1) is a tool that compares two lists and can give you the intersection or difference between two lists. The lists need to be sorted, but that's easy to achieve.
To get your arrays into a sorted list suitable for comm:
$ printf '%s\n' "${A[@]}" | LC_ALL=C sort
That will turn array A into a sorted list. Do the same for B.
To use comm to return the ...
16
In your case parenthesis () are used as array definition, for example
a=(one two three) # array definition
echo "${a}" # print first element of array a
echo "${a[0]}" # print first element of array a
echo "${a[1]}" # print *second* element of array a
echo "${#a[@]}" # print number of elements in array a
If you put single variable in ...
Only top voted, non community-wiki answers of a minimum length are eligible
Related Tags
array × 522bash × 350
shell-script × 154
shell × 48
awk × 45
zsh × 36
variable × 33
scripting × 23
text-processing × 22
string × 21
linux × 20
for × 17
function × 16
grep × 14
ksh × 13
associative-array × 13
quoting × 12
arguments × 12
sed × 11
bash-array × 11
sort × 10
read × 9
files × 8
csv × 8
variable-substitution × 8