Powershell 正则表达式替换/删除路径结尾

问题描述 投票:0回答:4

我正在尝试在 PowerShell 中提取路径的特定部分。

代码如下所示:

$Path -replace '/\/(main)?\/?$/gis',""

这里有几个例子和预期的输出:

示例 1
$Path: "C://Users/admin/Documents/StackOverflow/"
预期输出:“C://Users/admin/Documents/StackOverflow”
实际输出:“C://Users/admin/Documents/StackOverflow/”

示例 2
$Path: "C://Users/admin/Documents/StackOverflow/main"
预期输出:“C://Users/admin/Documents/StackOverflow”
实际输出:“C://Users/admin/Documents/StackOverflow/main”

示例 3
$Path: "C://Users/admin/Documents/StackOverflow/main/"
预期输出:“C://Users/admin/Documents/StackOverflow”
实际输出:“C://Users/admin/Documents/StackOverflow/main/”

有人可以告诉我我做错了什么吗?

代码在 JavaScript 中运行良好,所以我想知道为什么它在 PowerShell 中不起作用。

我也尝试了以下模式但没有成功:

'/(main)?/?$'

'(?s)/main/?$'

regex powershell path trim
4个回答
3
投票

.NET 中的模式语法是

(?<options>)<pattern>
,而不是
/<pattern>/<options>

$Path -replace '(?s)/(main)?/?$'

对于其余选项:

g
是隐含的,
i
由PowerShell自动注入

正如 Wiktor Stribiżew 在 评论 中指出的那样,

s
选项不会为您提供给定模式的任何内容,但为了完整性,我将其包括在内


1
投票

使用或:

$inputs = @("C://Users/admin/Documents/StackOverflow/",
            "C://Users/admin/Documents/StackOverflow/main",
            "C://Users/admin/Documents/StackOverflow/main/");
foreach($input in $inputs)
{
   $result = $input -replace '/(main)/?$|/$',""
   Write-Host $result
}

0
投票

我认为您需要删除最后一个字符“/”或严格从目录“/main/”开始的所有内容。同时类似“/maindir/”的目录应该不用考虑了吧?

测试这个条件:

(/main/.*?|/main|/)$

-1
投票

Mathias 的有用答案 很好地解释了PowerShell 语法 问题与您的方法。

但是,要获得所需的输出,您的正则表达式本身也需要调整

'(/main)?/?$'

以下根据您的示例路径生成所需的输出:

# Sample paths
$paths = @(
  "C://Users/admin/Documents/StackOverflow/"
  "C://Users/admin/Documents/StackOverflow/main"
  "C://Users/admin/Documents/StackOverflow/main/"
)

$paths -replace '(/main)?/?$'

# Variant, if you need to deal with both "\" and "/" as path separators:
#    $paths -replace '([/\\]main)?[/\\]?$'
  • 有关正则表达式的解释以及使用它进行实验的能力,请参阅this regex101.com page,但简而言之:它匹配每个字符串的end (

    $
    ) 中的以下任何内容:a
    /
    ,如果存在 (
    ?
    ),前面有
    /main
    ,如果存在,所以实际上
    /
    /main
    /main/
    都是匹配的。

    • 顺便说一句:为了将可选逻辑(

      (…)
      )应用于整个字符串
      ?
      ,需要一个分组结构(main)。 
      (…)
      是一个 capturing 组,这在你的情况下不是必需的,因为你不需要参考它以后捕获的内容。
      因此,优化(这里几乎没有实际影响)是使用 non-capturing 组,
      (?:…)

      $paths -replace '(?:/main)?/?$'
      
  • 请注意,no 替换操作数已提供给

    -replace
    意味着
    ''
    (空字符串),因此会导致 removal 匹配的内容。

  • 如您所见,当给定 array 输入字符串时,

    -replace
    对每个元素 进行 运算,并返回结果数组。

    • 为了处理单个 多行 字符串,您可以应用

      (?m)
      内联正则表达式选项,以便匹配 each line 上的模式,因为
      $
      然后不引用整个字符串的末尾,但到每一行的末尾:

      $multiLineStringWithPaths -replace '(?m)(?:/main)?/?$'
      
© www.soinside.com 2019 - 2024. All rights reserved.