25

I see this in a shell script.

variable=${@:2}

What is it doing?

  • Is that exactly how it showed in the script? The syntax looks like an array but is missing some pieces. Can you please post a couple of the lines around this line from the script? – slm Sep 30 '13 at 12:44
  • That is a variable starting from the second letter. var="my_value"; echo var="${var[@]:2}"; echo "$var" See the difference? – Valentin Bajrami Sep 30 '13 at 12:47
31

It's showing the contents of the special variable $@, in Bash. It contains all the command line arguments, and this command is taking all the arguments from the second one on and storing them in a variable, variable.

Example

Here's an exampe script.

#!/bin/bash

echo ${@:2}

variable=${@:3}
echo $variable

Example run:

./ex.bash 1 2 3 4 5
2 3 4 5
3 4 5

References

  • 8
    Note that the technique shown mashes the given arguments into a single string. If you need to keep them as separate arguments, use an array: vars=( "${@:2}" ) – glenn jackman Sep 30 '13 at 13:11
  • @glennjackman - thanks for pointing that out. – slm Sep 30 '13 at 13:15
  • 2
    Also note the use of the curly brackets. You are supposed to always use curly brackets, but Bash allows you to omit them when the context is unambiguous. Therefore, $@ and ${@} are identical, although the latter is the "more correct" syntax. You have to use the brackets with ${@:2}, because $@:2 is ambiguous and would therefore be interpreted as ${@}:2, which is not the same thing. – Paddy Landau Sep 30 '13 at 18:33
13

That's a ksh feature also found in bash and recent versions of zsh.

In ksh and bash, you can access several elements of an array by using the ${array[@]:first:length} syntax, which expands to up to length (or all if length is omitted) elements of the array array (in the list of elements of the array sorted numerically on the indexes), starting with the first one with index greater or equal to first. When in scalar context (like here in an assignment to a scalar variable) the list of elements is joined with space characters with bash and ksh93 and with the first character of $IFS (or nothing if $IFS is empty or space if it is unset) with zsh.

For instance:

$ a[23]=a a[5]=b a[235]=c a[45]=d
$ x=${a[@]:12:2}; printf '<%s>\n' "$x"
<a d>

$@ is a special case. $@ is the array of positional parameters ($1, $2...). But when used with :, $0 is also included. So ${@:1} is the same as $@, not ${@:0} like for other arrays.

In zsh, it's slightly different. zsh added the ksh syntax only recently for compatibility but has its own syntax for selecting ranges of elements.

Contrary to ksh and bash, zsh arrays are a different variable type from scalar variables, are not sparse (zsh has associative arrays as another variable type) and start at index 1 instead of 0.

For zsh, you access array element ranges with $a[first,last] (where last can also be negative to count backwards from the end).

In zsh,

a[23]=a a[5]=b a[235]=c a[45]=d

creates an array with 235 elements, most of them empty. $a[12,50] would expand to elements 12 to 50, and ${a[@]:12:2} would only expand to the (empty) $a[12] and $a[13] elements. As a special case, and again for portability with ksh93 and bash, zsh also accepts a 0 first element for $@ and treats that as $0.

So, you can use ${a[@]:x:n} and ${@:x:n} portably across all 3 shells, but only for non-sparse arrays, and pay attention to the value of IFS.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.