What does this ${@:2} mean in shell scripting

39,171

Solution 1

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

Solution 2

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.

Share:
39,171

Related videos on Youtube

Lenin Raj Rajasekaran
Author by

Lenin Raj Rajasekaran

Updated on September 18, 2022

Comments

  • Lenin Raj Rajasekaran
    Lenin Raj Rajasekaran almost 2 years

    I see this in a shell script.

    variable=${@:2}
    

    What is it doing?

    • Admin
      Admin over 10 years
      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?
    • Admin
      Admin over 10 years
      That is a variable starting from the second letter. var="my_value"; echo var="${var[@]:2}"; echo "$var" See the difference?
  • Angel Todorov
    Angel Todorov over 10 years
    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}" )
  • Paddy Landau
    Paddy Landau over 10 years
    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.
  • information_interchange
    information_interchange about 4 years
    Thanks for explaining the array indexing syntax