使用 PowerShell,如何从一行文本中提取文件路径和名称?

Using PowerShell, how do I extract just the file path and name from a line of text?

提问人:HTWingNut 提问时间:11/14/2023 更新时间:11/14/2023 访问量:98

问:

如果我正在遍历一个文本文档,每一行都有一个这样的输出:

        Newer             432416 2020/04/04 01:50:14    S:\Steam\SteamLibrary\steam.dll

我只想提取文件名和路径:S:\Steam\SteamLibrary\steam.dll

我知道我是否将该行存储在变量中$textline = " Newer 432416 2020/04/04 01:50:14 S:\Steam\SteamLibrary\steam.dll"

我可以简单地使用以下结果:$textline.split (":")[-1]

\Steam\SteamLibrary\steam.dll

但是我如何让它包含驱动器号?有没有办法告诉它之前抓取一个字符并包含分隔符?S:

谢谢。

PowerShell 拆分 子字符串

评论

1赞 Abdul Niyas P M 11/14/2023
怎么样?[regex]::split($textline, "\s{2}")[-1]
0赞 iRon 11/14/2023
您可能想看一下更大的图景(文本文档中是否有标题?文件名/路径“属性”中是否有空格?)。无论如何,试试这个 ConvertFrom-SourceTable;如果没有标头:。如果文本文档中有标题,只需:$textline | ConvertFrom-SourceTable -Header Newer,Size,Date,Time,Filepath$textdocument | ConvertFrom-SourceTable | Foreach { $_.<filepath header> }

答:

3赞 mandy8055 11/14/2023 #1

您可以使用下面的正则表达式匹配来搜索每行中的文件路径

([A-Z]:\\(?:[^\\]+\\)*[^\\]+)$

上述正则表达式的解释:

  • [A-Z]: - 匹配驱动器名称,后跟文本 。在我用于不区分大小写的匹配的脚本中。:?i
  • \\(?:[^\\]+\\)* - (因为它是一个特殊字符,所以需要转义),后跟一个与至少一个字符匹配的非捕获组 except()。非捕获组可以存在 0 次或更多次,因为可以有嵌套路径。在这里,您还可以包含换行符否定列表。请看这里。我没有这样做,因为我们正在迭代一行,所以它不是必需的。\\
  • [^\\]+- 最后,这部分匹配任何不是反斜杠的字符,基本上与路径的文件名匹配。
  • $- 表示行尾。

$text_file = "path_to_your_file.ext"
$lines = Get-Content $text_file
$pattern = "(?i)([A-Z]:\\(?:[^\\]+\\)*[^\\]+)$"

foreach ($textline in $lines) {
    $match = [regex]::Match($textline, $pattern)

    if ($match.Success) {
        $file_path = $match.Groups[1].Value
        Write-Host $file_path
    }
}

REGEX 演示

enter image description here

评论

0赞 HTWingNut 11/14/2023
是的,谢谢,我会试一试!我对正则表达式不太熟悉,我想我必须再读一遍。我也在想,如果它是以双斜杠“\”开头的 UNC 路径。使用您提供的演示站点,我设法使 UNC 路径正常工作,但不确定它是否最佳甚至正确:regex101.com/r/4Yyl1G/1
1赞 mandy8055 11/14/2023
@HTWingNut我会帮助你的。所以你是说如果路径以双斜杠开头并且没有驱动路径怎么办,对吧?
0赞 HTWingNut 11/14/2023
是的!好吧,它可能是带有冒号或双斜杠的驱动器号开始。
1赞 mandy8055 11/14/2023
@HTWingNut,好吧,那么你可以使用交替。类似 regex101.com/r/uXkZzc/1
1赞 HTWingNut 11/14/2023
这看起来可能会起作用!非常感谢!
3赞 Thomas 11/14/2023 #2

mandy8055 的回答会仔细检查路径是否有效,但如果你知道文件路径总是在 的末尾,并且 中的“列”用 4 个空格(或更多)分隔,那么这个正则表达式要快得多:$textLine$textLine

(?:.*\s{4})(.*)$

这个正则表达式的逻辑是简单地找到“最后 4 个空格”之后的所有字符,没有检查它是否是路径。

使用示例:

if($textLine -match "(?:.*\s{4})(.*)$"){
    $path = $matches[1]
    # process the path etc.
}