等同于powershell中的local,测试数组中是否包含元素

时间:2019-04-12 12:19:09

标签: arrays bash powershell scope contains

我想要在PowerShell中等效于此代码

function containsElement () {
  local e
  for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
  return 1
}

请帮助我

1 个答案:

答案 0 :(得分:2)

在PowerShell中,您不需要此功能,因为它带有collection-containment operators
-contains-in(它们的区别仅在于数组是否位于LHS或RHS):

# Sample value to test.
$element = 1

# Sample array to test against.
$array = 5, 3, 2, 1, 6

# Test if the value is in the array.
$contains = $element -in $array

# output the value of $contains
$contains

如预期的那样,以上方法产生True$true的输出表示)。

注意事项:PowerShell与传统的shell不同,它具有基于.NET的 rich类型系统,这意味着(隐含的)相等比较可能并不总是按预期进行;简而言之,由于自动类型转换,比较中的操作数顺序很重要,因此'0xa' -in 10, 'other'$true,而10 -in '0xa', 'other'不是-请参阅{{3}的底部}。


如果确实需要使用作为各个参数 传递的数组元素来复制Bash函数:

function containsElement {
    # Save the 1st argument passed and the remaining ones
    # in separate local variables, using a destructuring assignment.
    # $args is an automatic variable that contains the arguments
    # passed as an array ([object[]]), akin to $@ in Bash.
    $e, $arr = $args
    # Test, and implicitly output the Boolean result.
    $e -in $arr
}

# Sample call, equivalent of above.
containsElement 1  5 3 2 1 6

还请注意,PowerShell将布尔值作为 data (隐式或显式[bool]值)进行通信,而不是通过不可见状态信息(退出代码)以POSIX的方式进行传递像Bash这样的外壳程序-有关更多信息,请参见this answer的底部。


PowerShell中的局部变量与类似POSIX的外壳(例如Bash)中的局部变量

上方函数中的

$e$arr是局部变量,因此是隐含的;如果您想使这一事实明确,则可以使用$local:e, $local:arr = $args,但这绝对没有必要,因为 分配给PowerShell中的变量隐式且始终不变 在本地(当前)范围内创建它

这不同于类似POSIX的外壳,后者的分配没有local 要么修改父级范围内预先存在的变量;如果没有变量,则隐式在 top (脚本)范围内创建变量 [1]

  • 就像在POSIX一样的shell中一样,PowerShell中的后代作用域(子作用域及其子代...)会参见一个局部变量< / strong>。

    • 与类似POSIX的外壳程序(ksh [1] 除外)不同,PowerShell还提供了一种创建真正的本地变量的方法,即仅在定义范围内可见且可修改的变量,即通过 $private:范围修饰符:$private:var = 'truly local' [2]
      范围为$private的变量具有有效的行为,这是您期望的在 lexical 范围内的已编译编程语言(例如C#)中对局部变量的期望(相对于动态作用域内的脚本语言)。
  • 与类似POSIX的外壳不同,后代作用域不能通过不合格赋值 (或任何祖先作用域)修改调用者的本地变量变量。

    • 但是, PowerShell通过 $script:$scope:范围说明符为祖先范围提供了显式访问权限 ,也可以通过-ScopeGet-Variable cmdlet的 Set-Variable参数

有关PowerShell范围规则的更多信息,请参见this answer的底部。


[1]在类似POSIX的外壳中进行作用域演示

以下脚本可在bashdashzsh中使用(bashdash经常用作系统的默认Shell,{{1} }。

要使脚本在/bin/sh中运行,您必须将ksh关键字替换为local,并使用typeset关键字定义函数({{1 }}而不是function),因为function a { ...不了解a() { ...,仅使用ksh语法创建局部变量。
但是,与提到的其他类似POSIX的外壳不同,local然后创建一个在后代作用域中看不到的真正本地变量,就像PowerShell的function范围一样;换句话说:局部ksh变量始终是 函数局部变量,而后代作用域从不看到它们。

$private:

这将产生以下内容:

ksh

[2]在PowerShell中#!/usr/bin/env bash a() { local var='1' # create local variable. echo " calling scope before: [$var]" b # call function b echo " calling scope after: [$var]" } b() { echo " child scope before: [$var]" # calling scope's var. is visible var='1a' # modifies the *caller's* var. local var=2 var='2a' # modifies the *local* var. echo " child scope after: [$var]" newvar='hi' # assigning to a variable that doesn't exist in any scope # on the call stack creates it in the *top-level* scope. } # Call function a() a # var. created in b() without `local` is now visible. echo "script scope: [$newvar]" 范围的演示

  calling scope before: [1]
    child scope before:   [1]
    child scope after:    [2a]
  calling scope after:  [1a]
script scope: [hi]

也就是说,私有$private:仅在外部# & { ... } executes ... in a child scope. # Referencing a variable by itself implicitly outputs it (implicit `echo `). PS> $var = 'outer'; & { $private:var = 'inner'; $var; & { $var } } inner outer 内部直接可见;嵌套的$var再次看到了祖父母范围的{ ... }