【问题标题】:Unexpected token '-UFormat' in expression or statement表达式或语句中出现意外的标记“-UFormat”
【发布时间】:2018-12-03 15:09:51
【问题描述】:

我要获取列表

  • 文件/文件夹的完整路径名
  • 文件/文件夹的最后写入时间
  • 文件/文件夹的大小

基于最终用户想要的 3 条信息中的哪一条。 我希望扩展我的这个功能,以根据提供的输入容纳更多属性。下面给出的是我的代码的 sn-p 以及它之后的失败。

  • $Path 是路径,是输入
  • $CustomMetaList 是一个属性数组,它是一个输入。
    $BaseCmd = "Get-ChildItem $Path -Recurse"
    $Hidden = ""
    $FullName = ""
    $LastWriteTime = ""
    $Size = ""
    $PropList = ""
    $CustomMetaList = $CustomMetaList.split(",")
    foreach ($Meta in $CustomMetaList) {
        if ($Meta -eq "'Hidden'") {
            $Hidden = "-Force"
        }
        if ($Meta -eq "'FullName'") {
            $PropList = [String]::Join(",","@{e={`$_.FullName};width=250}")
        }
        if ($Meta -eq "'LastWriteTimeUtc'") {
            $PropList = [String]::Join(",",$PropList,"@{e={`$_.LastWriteTimeUtc -UFormat %s}}")
        }
        if ($Meta -eq "'Size'") {
            $PropList = [String]::Join(",",$PropList,"@{e={`$_.Length}}")
        }
    }
    Invoke-Expression "$BaseCmd $Hidden | Format-Table -HideTableHeaders -Property $PropList -AutoSize | Out-String -Width 5000"
}

当我尝试运行我的脚本时收到以下错误, 你知道出了什么问题吗?

调用表达式: 在行:1 字符:210 + ... stWriteTimeUtc -UFormat %s}},@{e={$_.Length}} -AutoSize |外串宽度 5000 + ~~~~~~~~ 表达式或语句中出现意外的标记“-UFormat”。 在行:1 字符:219 + ... meUtc -UFormat %s}},@{e={$_.Length}} -AutoSize |外串宽度 5000 + ~~ 表达式或语句中出现意外的标记“%s”。 在 E:\299955427760_GetData.ps1:114 char:5 + 调用表达式“$BaseCmd $Hidden | 格式表 -HideTableHeaders -Proper ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ParserError: (:) [Invoke-Expression], ParseException + FullyQualifiedErrorId : UnexpectedToken,Microsoft.PowerShell.Commands.InvokeExpressionCommand

【问题讨论】:

  • 与其构建要运行的命令,为什么不直接运行基本命令,通过Select-Object 发送该命令以构建仅包含所需属性的对象,最后将其发送给Format-Object? ///// 我看不出有任何理由去做……倒退……就像你在那里所做的那样。 [咧嘴]
  • @Lee_Dailey 这是我在 ps 新手中看到的一种奇怪的反模式,他们生成一些命令字符串并使用 Invoke-Expression 来运行它,而不仅仅是......运行命令字符串。
  • @TheIncorrigible1 - 我想你是对的。 [grin] 希望 OP 能从他的角度描述为什么
  • 感谢@TheIncorrigible1,我会牢记这一点,我的方法背后的基本思想是根据输入(对于名称、大小等属性)将命令构建为字符串lwt) 用户提供。快速在线搜索我想要的东西让我找到了 Invoke-Expression。不过,我没有检查这是否是最好的方法。

标签: powershell


【解决方案1】:

正如Ansgar Wiechers 中肯的建议,Invoke-Expression should be avoided,因为几乎总是有更好的解决方案,但也存在安全风险。

通常,对于使用不同参数迭代构造命令,参数splatting 是最佳解决方案,尽管在​​您的情况下这不是绝对必要的 - 请参阅底部部分。

但是,您的问题与Invoke-Expression的使用无关,因为是以下表达式导致了您的问题:

$_.LastWriteTimeUtc -UFormat %s  # !! Syntax error

您只能将-UFormat 传递给Get-Date cmdlet,而不能传递给变量或表达式:

Get-Date -Date $_.LastWriteTimeUtc -UFormat %s  # OK

此外,由于 Windows PowerShell v.5.1 中的一个错误(在 PowerShell Core 中已更正),Get-Date -UFormat %s 也会输出 fractional 秒,这是不正确的;你可以通过简单地转换为[int]来解决这个问题:

[int] (Get-Date -Date $_.LastWriteTimeUtc -UFormat %s)

(即使没有出现错误,您也可能希望这样做以接收 numeric 结果,因为Get-Date -UFormat 总是输出 strings)。

顺便说一句:另一个错误导致结果默认基于本地时间,而Unix时间戳需要基于UTC;由于您使用的是属性.LastWriteTimeUtc,因此您的代码不受影响。


这是一个避免 Invoke-Expression 并且更短的解决方案:

# Sample input values.
$Path = $env:TEMP
$CustomMetaList = 'FullName,Size,LastWriteTimeUtc'

# Construct the array of property definitions to pass to Select-Object
# based on the custom list, and record in $force whether hidden items 
# should be included.
$props = switch ($CustomMetaList -split ',') {
    'Hidden' { $force = $True; continue } # save in Boolean var.
    'FullName' { $_; continue }           # same name as property
    'Size' { 'Length'; continue }         # map 'Size' to 'Length'
    'LastWriteTimeUtc' {                  # calculated property
      @{ n=$_; e = { [int] (Get-Date -Date $_.LastWriteTimeUtc -UFormat %s) } }
    }
}


Get-ChildItem $Path -Recurse -Force:$force | 
  Format-Table -Property $props -HideTableHeaders -AutoSize |
    Out-String -Width 5000

注意switch 如何用于隐式迭代$CustomMetaList -split ',' 返回的数组元素。 switch 语句的分支处理程序在默认情况下all 进行测试,因此一旦找到匹配项,continue 将用于短路。警告:不要使用break,因为它会停止迭代更多的数组元素。

switch 语句迭代的输出被隐式收集在一个 array 中,该数组存储在 $props 中,稍后将传递给 Format-Table

-Force:$force 是一种模拟传递/不传递开关参数-Force 的效果的方法:如果$force$true,则与仅传递-Force 相同;否则,视为-Force 未通过。

这将产生类似:

FullName                              Length LastWriteTimeUtc
--------                              ------ ----------------
C:\path\to\sample.txt                 51     1543853694
# ...

【讨论】:

    猜你喜欢
    • 2018-07-25
    • 1970-01-01
    • 1970-01-01
    • 2014-11-12
    • 1970-01-01
    • 2018-05-04
    • 1970-01-01
    • 2020-10-20
    • 1970-01-01
    相关资源
    最近更新 更多