Search code examples
powershellargs

How to access last argument in PowerShell script (args)


I have following code:

foreach ($arg in $args) {
        Write-Host "Arg: $arg";
        $param1=$args[0]
}
Write-host "Number of args: " $args.Length
write-host Last Arg is: "$($args.count)"




I get this, when I run it:

./print_last_arg.ps1 a b c
Arg: a
Arg: b
Arg: c
Number of args:  3
Last Arg is: 3


What I would like to have is name of last argument, so:

Last Arg is: 3

should be:

Last Arg is: c

Sorry for such a stupid question but I am totally begginer in PS and cannot google the result...


Solution

  • PowerShell supports negative indices to refer to elements from the end of a collection, starting with -1 to refer to the last element, -2 to the penultimate (second to last) one, and so on.

    Therefore, use $args[-1] to refer to the last argument passed.

    For more information, see the conceptual about_Arrays help topic.


    Note that you can also use the results of expressions as indices; e.g., the equivalent of $args[-1] is $args[$args.Count-1] (assuming the array has at least one element).

    Additionally, you may specify multiple indices to extract a sub-array of arbitrary elements. E.g., $args[0, -1] returns a (new) array comprising the input array's first and the last element (assuming the array has at least two elements).

    .., the range operator is particularly useful for extracting a range of contiguous elements. E.g., $args[0..2] returns a (new) array comprising the first 3 elements (the elements with indices 0, 1, and 2).

    You can even combine individual indices with ranges, courtesy of PowerShell's + operator performing (flat) array concatenation. E.g., $args[0..2 + -1] extracts the first 3 elements as well as the last (assumes at least 4 elements).

    • Note: For syntactic reasons, if a single index comes first in the index expression, you need to make it an array with the unary form of , the array constructor operator, to make sure that + performs array concatention; e.g., $args[,-1 + 0..2] extracts the last element followed by the first 3.

    Pitfall: Combining a positive .. start point with a negative end point for up-to-the-last-Nth-element logic does not work as intended:

    Assume the following array:

    $a = 'first', 'middle1', 'middle2', 'last'
    

    It is tempting to use range expression 1..-2 to extract all elements "in the middle", i.e. starting with the 2nd and up to the penultimate element - but this does not work as expected:

    # BROKEN attempt to extract 'middle1', 'middle2'
    PS> $a[1..-2]
    middle1
    first
    last
    middle2
    

    The reason is that 1..-2, as a purely arithmetic range expression, expanded to the following array (whose elements happen to be used as indices into another array): 1, 0, -1, -2. And it is these elements that were extracted: the 2nd, the first, the last, the penultimate.

    To avoid this problem, you need to know the array's element count ahead of time, and use an expression to specify the end of the range as a positive number:

    # OK: extract 'middle1', 'middle2'
    # Note that the verbosity and the need to know $a's element count.
    PS> $a[1..($a.Count-2)]
    middle1
    middle2
    

    Unfortunately, this is both verbose and inconvenient, especially given that you may want to operate on a collection whose count you do not know in advance.

    GitHub issue #7940 proposes a future enhancement to better support this use case with new syntax, analogous to C#'s indices-and-ranges feature, so that the above could be written more conveniently with syntax such as $a[1..^1]