Powershell $this 变量在数组索引中不起作用

Powershell $this variable does not work inside array indexing

我正在尝试在 Powershell 中模拟 MATLAB 的“end”索引关键字(例如 A[5:end]),但我不想键入数组名称(例如 $array) 为

访问 $array.length
$array[0..($array.length - 2)]

如另一个 Stackflow question 中所述。我试过 $this

(0..7)[4..($this.Length-1)]

给出的 ($this.Length-1) 似乎被解释为 -1,如输出所示

4
3
2
1
0
7

这让我觉得 $this 在 [] 中用于索引数组时是空的。有没有一种方法可以让数组在不显式重复变量名的情况下引用自身,这样我就可以调用数组的方法来派生索引?这对于在利用方法链(如 a.b.c.d[4..end])的同时模拟逻辑索引非常方便。

PowerShell 没有任何引用“此索引访问运算符所针对的集合”的工具,但如果您想跳过 collection/enumerable 的前 N ​​项,您可以使用 Select -Skip:

0..7 |Select -Skip 4

补充

  • automatic $this variable 在索引表达式 ([...]) 中不可用 ,仅在自定义 classes (以指代手头的实例)并在脚本块中充当 .NET 事件委托(以指代事件发送者)。

  • 但是,对于您想要实现的目标,您不需要引用输入数组(集合)作为一个整体:相反, 一个 抽象符号 用于引用相对于输入数组的 end 的索引应该足够 ,并且理想情况下也适用于“所有剩余元素”逻辑。

您可以使用负索引来引用相对于输入数组末尾的索引[=139] =],但 仅适用于 个人 索引 :

# OK: individual negative indices; get the last and the 3rd last item:
('a', 'b', 'c', 'd')[-3, -1] # -> 'b', 'd'

不幸的是,因为索引表达式中的 .. 指的是独立的 general-purpose range operator,所以 而不是 当负索引用作 范围端点时 range-based 数组切片 工作 :

# !! DOES NOT WORK: 
# *Flawed* attempt to get all elements up to and including the 2nd last,
# i.e. to get all elements but the last.
# 0..-2 evaluates to array 0, -1, -2, whose elements then serve as the indices.
('a', 'b', 'c', 'd')[0..-2] # -> !! 'a', 'd', 'c'

也就是说,一般范围操作 0..-2 的计算结果为数组 0-1-2,结果索引用于提取元素。

正是这种行为目前需要对 everything-except-the-last-N-elements 逻辑 的索引表达式中的数组进行不方便的显式引用,例如 $array[0..($array.length - 2)]在你的问题中提取除最后一个元素之外的所有元素。

GitHub issue #7940 proposes introducing new syntax that addresses this problem, by effectively implementing C#-style ranges:

虽然没有就语法达成一致,也没有承诺实施此增强功能,但可以选择直接借用 C# 的语法:

Now Potential future syntax Comment
$arr[1..($arr.Length-2)] $arr[1..^1] From the 2nd el. through to the next to last.
$arr[1..($arr.Length-1)] $arr[1..] Everything from the 2nd el.
$arr[0..9] $arr[..9] Everything up to the 10th el.
$arr[-9..-1] $arr[^9..] Everything from the 9th to last el.

注意 from-the-end、1 索引语法的逻辑(例如,^1 指的是 last 元素)当作为范围端点:是up-to-but-排除逻辑,所以..^1表示:到索引最后一个之前,即倒数第


至于解决方法

Select-Object-Skip/-SkipLast一起使用在简单情况下很方便,但是:

  • 与索引表达式 ([...]) 相比表现不佳(见下文)
  • 缺乏后者的灵活性[1]
    • 一个值得注意的限制是您不能在单个 Select-Object 调用中同时使用 -Skip-SkipLastGitHub issue #11752 建议取消此限制。

例如,在下面的示例中(它补充了 Mathias 的 -Skip 示例),它提取了除最后一个元素之外的所有元素:

# Get all elements but the last.
$arr | Select-Object -SkipLast 1
  • 数组$arr枚举,即它的元素通过管道一个一个发送,一个称为 streaming.

    的过程
  • 捕获时,流元素被收集在常规的 [object[]] 类型的 PowerShell 数组中,即使输入数组是强类型的 - 然而,这种严格类型的损失也适用通过 [...].

    提取多个元素

根据数组的大小和所需的切片操作数,性能差异可能很大。


[1] 值得注意的是,您可以在 [...] 中使用 任意表达式 ,这在 中有更详细的讨论。