【问题标题】:Performing A String Operation in a -replace Expression在 -replace 表达式中执行字符串操作
【发布时间】:2018-03-14 12:28:06
【问题描述】:

我正在尝试使用 String.Substring() 从某个位置将每个字符串替换为其子字符串。我很难找出正确的语法。

$dirs = Get-ChildItem -Recurse $path | Format-Table -AutoSize -HideTableHeaders -Property @{n='Mode';e={$_.Mode};width=50}, @{n='LastWriteTime';e={$_.LastWriteTime};width=50}, @{n='Length';e={$_.Length};width=50}, @{n='Name';e={$_.FullName -replace "(.:.*)", "*($(str($($_.FullName)).Substring(4)))*"}} | Out-String -Width 40960

我指的是下面的表达式

e={$_.FullName -replace "(.:.*)", "*($(str($($_.FullName)).Substring(4)))*"}}

第 4 个字符的子字符串没有替换路径的全名。 相关路径超过 4 个字符。

当我运行脚本时,全名的输出只是空的。 有人可以帮我解决语法

编辑 未更改的字符串列表(如 Get-ChildItem 递归)将是

D:\this\is\where\it\starts D:\this\is\where\it\starts\dir1\file1 D:\this\is\where\it\starts\dir1\file2 D:\this\is\where\it\starts\dir1\file3 D:\this\is\where\it\starts\dir1\dir2\file1

$_.FullName 因此将采用上面列出的每个字符串的值。 给定一个像 D:\this\isD:\this\is\where 这样的输入,然后我正在计算这个输入的长度(包括分隔符 @987654326 @) 然后将$_.FullName 替换为从第 n 个位置开始的子字符串,其中 n 是输入的长度。

如果输入为 D:\this\is,则长度为 10。 预期输出是

\哪里\它\开始 \where\it\starts\dir1\file1 \where\it\starts\dir1\file2 \where\it\starts\dir1\file3 \it\starts\dir1\dir2\file1

【问题讨论】:

  • 您能否编辑您的帖子并举例说明未更改的字符串是什么以及所需的字符串是什么?很难准确理解您要做什么。
  • 另外请说明what you are trying to achieve。看起来您正在尝试构建某种摘要报告;也许有更好的方法。
  • 如果您只想删除前导 D:\,您应该这样做:$_.FullName -replace '^.:\\'。如果要删除特定的父路径,可以这样做:$_.FullName -replace ('^' + [regex]::Escape($parent))。如果您必须使用固定长度,您可以这样做:$_.FullName -replace '^.{4}'.
  • 那么你只是想删除驱动器和“$Path”的第一个路径吗?您可以通过执行 ".Substring($Path.Length)" 来使其动态化
  • 感谢@AnsgarWiechers,它是如此简单:),作为 Powershell 的新手,对正则表达式并不熟悉,我想我决定使用最复杂的解决方案来实现这一点。如果您将此作为答案发布,我可以将其标记为已解决 :)

标签: powershell


【解决方案1】:

如果你想从一个字符串中删除一个特定的前缀,你可以这样做:

$prefix = 'D:\this\is'
...
$_.FullName -replace ('^' + [regex]::Escape($prefix))

要删除给定长度的前缀,您可以执行以下操作:

$len = 4
...
$_.FullName -replace "^.{$len}"

【讨论】:

    【解决方案2】:

    遇到问题时,简化:

    这个函数会做你显然想要完成的事情:

    Function Remove-Parent {
      param(
        [string]$Path, 
        [string]$Parent) 
      $len = $Parent.length
      $Path.SubString($Len)
    }
    

    以下不是您可能会使用的方式,但确实表明该函数返回了预期的结果:

    @'
    D:\this\is\where\it\starts
    D:\this\is\where\it\starts\dir1\file1
    D:\this\is\where\it\starts\dir1\file2
    D:\this\is\where\it\starts\dir1\file3
    D:\this\is\where\it\starts\dir1\dir2\file1
    '@ -split "`n" | ForEach-Object { Remove-Parent $_ 'D:\This\Is'  }
    
    # Outputs
    \where\it\starts
    \where\it\starts\dir1\file1
    \where\it\starts\dir1\file2
    \where\it\starts\dir1\file3
    \where\it\starts\dir1\dir2\file1
    

    只需使用当前路径 ($_.fullname) 和您希望删除的“前缀”调用函数。

    上面的函数严格按照“长度”执行此操作,但您可以轻松调整它以匹配实际字符串,使用字符串替换或正则表达式替换。

    Function Remove-Parent {
      param(
        [string]$Path, 
        [string]$Parent
      )
      $remove = [regex]::Escape($Parent)
      $Path -replace "^$remove"
    }
    

    输出与上面相同。

    【讨论】:

      猜你喜欢
      • 2016-12-02
      • 2013-05-07
      • 1970-01-01
      • 2011-04-06
      • 1970-01-01
      • 2021-01-08
      • 1970-01-01
      • 2011-12-20
      相关资源
      最近更新 更多