Ranges & Slicing Syntax

Ion supports a universal syntax for slicing strings and arrays. For maximum language support, strings are sliced and indexed by graphemes. Arrays are sliced and indexed by their elements. Slicing uses the same [] characters as arrays, but the shell can differentiate between a slice and an array based on the placement of the characters (immediately after an expansion).

NOTE: It's important to note that indexes count from 0, as in most other system programming languages.

NOTE: ... and ..= can be used interchangeable.

Exclusive Range

The exclusive syntax will grab all values starting from the first index, and ending on the Nth element, where N is the last index value. The Nth element's ID is always one less than the Nth value.

let array = [{1...10}]
echo @array[0..5]
echo @array[..5]

let string = "hello world"
echo $string[..5]
echo $string[6..]
1 2 3 4 5
1 2 3 4 5
hello
world

Inclusive Range

When using inclusive ranges, the end index does not refer to the Nth value, but the actual index ID.

let array = [{1...10}]
echo @array[0...5]
1 2 3 4 5 6

The = character may be used instead of the third dot.

echo @array[0..=5]
1 2 3 4 5 6

Descending Ranges

Ranges do not have to always be specified in ascending order. Descending ranges are also supported. However, at this time you cannot provide an descending range as an index to an array.

echo {10...1}
echo {10..1}
10 9 8 7 6 5 4 3 2 1
10 9 8 7 6 5 4 3 2

Negative Values Supported

Although this will not work for arrays, you may supply negative values with ranges to create negative values in a range of numbers.

echo {-10...10}
-10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10

Stepping Ranges

Stepped ranges are also supported.

Stepping Forward w/ Brace Ranges

Brace ranges support a syntax similar to Bash, where the starting index is supplied, followed by two periods and a stepping value, followed by either another two periods or three periods, then the end index.

echo {0..3...12}
echo {0..3..12}
0 3 6 9 12
0 3 6 9

Stepping Forward w/ Array Slicing

Array slicing, on the other hand, uses a more Haskell-ish syntax, whereby instead of specifying the stepping with two periods, it is specified with a comma.

let array = [{0...30}]
echo @array[0,3..]
0 3 6 9 12 15 18 21 24 27 30

Stepping In Reverse w/ Brace Ranges

Brace ranges may also specify a range that descends in value, rather than increases.

echo {10..-2...-10}
echo {10..-2..-10}
10 8 6 4 2 0 -2 -4 -6 -8 -10
10 8 6 4 2 0 -2 -4 -6 -8

Stepping In Reverse w/ Array Slicing

Arrays may also be sliced in reverse order using the same syntax as for reverse. Of course, negative values aren't allowed here, so ensure that the last value is never less than 0. Also note that when a negative stepping is supplied, it is automatically inferred for the end index value to be 0 when not specified.

let array = [{0...30}]
echo @array[30,-3..]
30 27 24 21 18 15 12 9 6 3 0

Process Expansions Also Support Slicing

Variables aren't the only elements that support slicing. Process expansions also support slicing.

echo $(cat file)[..10]
echo @(cat file)[..10]