PowerShell 脚本:您可以创建一个动态更新变量($var.substring([int32],[int32]))吗?

PowerShell 脚本:您可以创建一个动态更新变量($var.substring([int32],[int32]))吗?

更新/重写的问题

以下是对一些人认为令人困惑的问题的重写。然而,在了解到我希望实现的目标无法实现后,我重写了这个问题。不过,我提供了一个解决方法作为答案,以防将来其他人可能有类似的问题。

此外,如果您阅读评论并看到对 的引用$base,则最初使用的是该变量。但是,随着这个问题/答案变得更加健壮,它$base被替换为 $variable,以使其更加通用,并希望防止将来某些读者产生混淆,询问 是什么$base$base并且它的替换$var是字符串。


我的IF-THEN条件通常包含四个或更多条件。因此,IF在创建后续条件(例如 等)时,语句变得非常“繁忙”且难以解读ELSEIF。这使得确保我编写的条件语句能够产生我想要的输出变得更加困难。

例如,我IF在脚本中有以下语句:

if (
  (Test-Path -Path "$variable") -eq $true -and
  $variable.trim().substring(1,1) -eq ':'-and 
  $variable.trim().len() -le 3 -and 
  $variable.trim().len() -ge 2
) {
  <some commands>
}

我想要做的是确定是否存在一些可以用来缩短一些较长的命令的语法(即单行命令)。 更新说明:以下是不可能的,但下面的答案中有一个解决方法。

例如,我想缩短它$variable.trim().substring(1,1),以便更容易阅读(即占用更少的屏幕空间)。但是,我仍然希望它相对于部分是动态的.substring()。那么,我可以创建一些看起来像$varSubStr([int32],[int32])等于的语法$bast.trim().substring([int32],[int32])吗?

因此,每当我需要 $variable 的子字符串时,我都可以调用$varSubStr(1,1)。(更新说明:我想要创建一个函数 - 只是在写这个问题时我没有意识到这一点)。

因此,当我从上面编写相同的语句时,它会通过替换而IF缩短。但是,它仍然是动态的,因此我可以更改子字符串的值。新语句将如下所示:$varSubStr(1,1)$variable.trim().substring(1,1)IF

if (
  (Test-Path -Path "$variable") -eq $true -and 
  $varSubStr(1,1) -eq ':'-and 
  $variable.trim().len() -le 3 -and 
  $variable.trim().len() -ge 2
) {
  <some commands>
}

同样,我可以将其缩短$variable.trim().length()$varLen。我应该指出,$variable变量在脚本中处理时可能会发生变化;因此$varLen在调用时需要动态更新(更新说明:再次重申,我所描述的是一个功能——我只是当时没有意识到这一点)。

那么该IF语句可能看起来像这样:

if (
  (Test-Path -Path "$variable") -eq $true -and
  $varSubStr(1,1) -eq ':'-and
  $varLen -le 3 -and
  $varLen -ge 2
) {
  <some commands>
}

这更简短并且更容易阅读。

那么,PowerShell 中是否存在某种单行语法可以实现这一点(更新说明:答案是否定的;需要的是一个函数)?

更新说明(对于可能正在阅读此文的新手):变量$var是静态对象,不会动态更新。除非您设置新值,否则$var=<some value>它不会动态更新。当我提到$varSubStr()或时,$varLen我只是将它们用作占位符,试图描述我希望我的输出是什么样子。请不要认为变量是动态更新的。如果您需要动态更新内容,则需要创建一个函数。


原文如下


是否存在一种语法可以在 PowerShell 中实现以下操作 - 即我可以将行开头更改为什么$b才能使该行真正起作用?

# Start Script

[string]$ReallyLongVariableNameThatIsUsefulAsADescription="AStringThatRunsOnandOnandOn"

$b=$ReallyLongVariableNameThatIsUsefulAsADescription.trim().substring

Write-Output $b(0,8)

# End Script
PS c:\<script.ps1>

AStringT

PS c:\

我意识到我可以创建一个完成任务的简短函数,我想知道是否存在像上面所示的单行解决方案。

谢谢。

答案1

正如@postanote 所说,变量是静态值,不能动态改变。

我正在寻找的解决方案是函数。我可以有效地创建一个单行代码,将其放入我的IF语句中,该语句将调用一个函数,该函数使用静态变量的当前值并返回我在脚本中需要评估的新值。

因此,为了清楚起见,我想在问题中创建的“动态变量”有一个以 PowerShell 函数形式呈现的解决方案。使用函数就是解决方案。


使用函数的解决方案/解决方法


我最根本的问题是,向变量添加.trim().substring([int32],[int32]).trim().len()会使我的代码看起来很复杂,更难理解。我想缩短调用所需的字符数$variable.trim().substring([int32],[int32])

使用函数,我可以创建一个命令,(varSubStr [int32] [int32])当调用时,评估$variable.trim().substring([int32],[int32])并返回其值。

对于我的解决方案/解决方法,我决定使用三个函数;一个函数是我正在处理的脚本的外部函数(因为它被其他脚本使用),两个函数嵌入在脚本中。创建这些函数使阅读长IF语句变得更容易。

最初,在我的脚本中,我会有如下几行:

###### START OF SCRIPT 

###### Various commands within the script
   
if (
  (Test-Path -Path "$variable") -eq $true -and
  $variable.trim().substring(1,1) -eq ':' -and
  $variable.trim().len() -le 3 -and
  $variable.trim().len() -ge 2
) {
  <some commands>
}

###### Various commands within the script

###### END OF SCRIPT

IF这使得解读条件逻辑变得乏味。乏味使得确定此条件语句的逻辑是否以语句块中预期的方式作用于变量变得更具挑战性IF-THEN

最终,当使用函数完成与上述语句相同的任务时,上述IF块将如下所示IF-THEN

if (
  (Test-Path -Path "$variable") -eq $true -and
  (varSubStr_1_1) -eq ':' -and
  (varLen) -le 3 -and (varLen) -ge 2
) {
  <some commands>
}

在上面的语句中,替换函数和 的IF函数分别是和。这些函数定义如下:$variable.trim().substring(1,1)$variable.trim().len()varSubStr_1_1varLen

###### The following function, `Get-TrimThenSubStr` is defined outside
###### the scope of my script. It is included here as it is referenced
###### in the embedded functions in my script. 

# The following function, `Get-TrimThenSubStrTrim`requires the user to 
# enter three parameters $InputString,$StartPositiotnstring,$EndPosition
# and return a substring from the `$InputString`

# Function Syntax: Get-TrimThenSubStr -InputString [string]$InputString 
# -StartPosition [int32]$StartPositionOfSubstring 
# -EndPosition [int32]$EndPositionOfSubString

##### Note: This function, Get-TrimThenSubStr, is referenced by the embedded 
##### function, varSubStr_1_1, that I define below inside the main script.

function Get-TrimThenSubStr {

  [CmdletBinding()]
  [Alias("TrimSubStr","TrSubStr","TrimThenSubString")]
  param (
    [Parameter(Mandatory)][Alias("Input")]
    [string]$InputString,
    [Parameter(Mandatory)][Alias("Start")]
    [int32]$StartPosition,
    [Parameter(Mandatory)][Alias("End")]
    [int32]$NumberOfCharacters
  )
    
  $input=$InputString
  $start=$StartPosition
  $char=$NumberOfCharacters
    
  if (!($start -match "^[\d\.]+$")) {
    $start=(Invoke-Expression "$start")
  }
  if (!($char-match "^[\d\.]+$")) {
    $char=(Invoke-Expression "$char")
  }
    
  return $input.Trim().Substring($start,$char)
}

----------

MyScript {
    
  ###### START OF SCRIPT

  ###### IMPORTANT NOTE
  ###### The variable, $variable, is defined and used throughout the script
  ###### prior to it being called by the functions below or IF-THEN 
  ###### statements.

  # The following script, varLen, is embedded in this script and not
  # accessible outside this script.
  # The function, varLen, returns the length of the string, $variable
  # Syntax: varLen

  ###### Note: this is an embedded functions that acts upon variables
  ###### defined in myScript (i.e. $variable). As such it is designed
  ###### without input parameters.

  function varLen {
    return "$variable".trim().Length
  }

  # The following function, varSubStr_1_1, is embedded in this script
  # and not accessible outside this script.
  # This script relies on the external function, Get-TrimThenSubStr,
  # to execute.
  # The function, varSubStr_1_1, below, will return a substring from
  # $variable starting at position 1 and for 1 character.
  # Syntax: varSubStr_1_1
  ###### Note: this is an embedded function that acts upon variables
  ###### defined in MyScript (i.e. $variable). As such it is designed
  ###### without parameters
  ###### Note: While this function is very narrow, its primary purpose is
  ###### to make it easier to read conditions within an 
  ###### IF-THEN statement - not add functionality

  function varSubStr_1_1 {
    # Call the function, varLen, to get $variable length
    if ((varLen) -lt 2) {
      return $variable
    } 
    else {
      # Call external function, Get-TrimThenSubstr, and enter parameters
      # -InputString <$variable> -StartPosition <1> -EndPosition <1>
      
     return Get-TrimThenSubStr `
      -InputString $variable `
      -StartPosition 1 `
      -EndPosition 1
  }

}

###### Various commands/logic within MyScript

# In the following IF-Then statement, the functions, varSubStr_1_1 and
# varLen can be substituted in place of ($variable.trim().substring(1,1))
# and ($variable.trim().len()), respectively

if (
  (Test-Path -Path "$variable") -eq $true -and
  (varSubStr_1_1) -eq ':' -and
  (varLen) -le 3 -and
  (varLen) -ge 2
) {
    <some commands>
}
else {
    <some commands>
}

###### Various commands/logic within MyScript

###### END OF SCRIPT

创建函数varSubStr_1_1(依赖于外部脚本Get-TrimThenSubStr)并且varLen是“单行”,我想缩短IF-THEN语句中的字符数,以便在阅读时更容易理解。


最后,如果我想进一步缩短声明中的内容IF,我意识到我还可以做一些其他的事情,例如:

  • 由于计算结果为 $true 或 $false,因此-eq $true从中消除。但是,对我来说,通过明确添加条件来解释会更快。(Test-Path -Path $variable") -eq $true(Test-Path -Path $variable")-eq $true
  • (Test-Path -Path $variable)类似功能(PathExists)可以进一步缩短文本。
  • (varSubStr_1_1 -eq ":")可以通过-eq ":"在函数内评估并返回 $true 或 $false 来进一步缩短,然后将其重命名为:varSubStr_1_1_SemiColon

经过这样的改进,我可以得到如下结果:

if (
  (PathExists) -and
  (varSubStr_1_1_IsSemiColon) -and
  (varLen) -le 3 -and
  (varLen) -ge 2
)

现在,我写完这个,可能最终会这么做。我知道这会占用更多 CPU 时间,但这与脚本最终执行的操作无关。


更新


我最终添加了一些附加函数,使其IF-THEN更易于阅读。例如:

if (
  (varPathExists) -and
  (varLenInclsvOf 2 2) -and
  (varSubStr_1_1_Is:_:)
)

其中(varPathExists)(varLenInclsOf [int32][ [int32])(varSubStr_1_1_Is:_:)是返回布尔值的函数。

虽然我不会分解每个函数,但唯一可能不言自明的是(varLenInvlsOf)(varLenInvlsOf)是短语“可变长度包括”的缩写。它需要两个参数,即后面的 [int32],以指示子字符串的开始和结束时间,包括这些数字。

因此,简而言之,这个解决方案/练习实际上讨论了如何使用函数来缩短较长的命令变量。显然,如果你使用太多函数,它也会变得同样令人困惑。但就我而言,它很有效,并且有助于使许多逻辑IF-THEN语句更容易理解并避免错误。

相关内容