【问题标题】:PowerShell Replace Syntax: Regex Substitution and Environmental VariablePowerShell 替换语法:正则表达式替换和环境变量
【发布时间】:2020-06-23 20:47:58
【问题描述】:

我正在尝试同时替换正则表达式和环境变量,但找不到正确的语法(因为单引号和双引号不匹配)。我正在开发的短脚本将重命名文件。以下是我尝试过的几种设置方式。

# Original File Name: (BRP-01-001-06K48b-SC-CC-01).tif
# Desired File Name:  (BRP-12-345-06K48b-SC-CC-01).tif

# Variables defined by user:
PS ..\user> $pic,$change="01-001","12-345"

# The problem is with the "-replace" near the end of the command
PS ..\user> get-childitem .\* -recurse | where-object {$_.BaseName -match ".*\(BRP-$pic-.{15}\).*"} | foreach-object {$orig=($_.FullName); $new=($orig -replace "(\(BRP-)($pic)(-.{15}\))", '$1$change$3'); echo $new}
PS ..\user> (BRP-$change-06K48b-SC-CC-01).tif

# Also tried:
PS ..\user> get-childitem .\* -recurse | where-object {$_.BaseName -match ".*\(BRP-$pic-.{15}\).*"} | foreach-object {$orig=($_.FullName); $new=($orig -replace "(\(BRP-)($pic)(-.{15}\))", "`$1$change`$3"); echo $new}
PS ..\user> $112-345-06K48b-SC-CC-01).tif

# If I put a space before $change:
PS ..\user> get-childitem .\* -recurse | where-object {$_.BaseName -match ".*\(BRP-$pic-.{15}\).*"} | foreach-object {$orig=($_.FullName); $new=($orig -replace "(\(BRP-)($pic)(-.{15}\))", "`$1 $change`$3"); echo $new}
PS ..\user> (BRP- 12-345-06K48b-SC-CC-01).tif

在最后一个示例中,如果我在 $change 之前添加空间,它“有效”......但我不想要空间。我意识到我可以做另一个replace 操作来修复空间,但如果可能的话,我想在一个命令中完成所有这些操作。

我需要同时使用环境变量和正则表达式替换什么语法?

此外,出于好奇,一旦工作,这将替换文件名中的所有匹配项还是仅替换第一个匹配项。例如,将文件:

"Text (BRP-01-001-06K48b-SC-CC-01) Text (BRP-01-001-06K48b-SC-OR-01)"

改为:

"Text (BRP-12-345-06K48b-SC-CC-01) Text (BRP-12-345-06K48b-SC-OR-01)"

或者只有第一个匹配,比如:

"Text (BRP-12-345-06K48b-SC-CC-01) Text (BRP-01-001-06K48b-SC-OR-01)"

【问题讨论】:

标签: regex powershell replace


【解决方案1】:

最佳做法是将捕获组名称括在 {} 中,或在替换字符串中使用命名捕获组。在您的第二个示例中使用 {} 应该会很好。

"Text (BRP-01-001-06K48b-SC-CC-01) Text (BRP-01-001-06K48b-SC-OR-01)" -replace "(\(BRP-)($pic)(-.{15}\))", "`${1}$change`${3}"

当 PowerShell 变量、捕获组和字符串文字位于替换字符串中时,不能使用单引号括起来。使用双引号可以实现内部扩展。因此,您需要使用反引号转义 $ 来识别捕获组。

您的第二个示例具有正确的语法,通常,但是因为$change 以数字开头,它会产生意想不到的后果。您在替换字符串中转义 $ 以使用捕获组 1 和 3。由于$change 的计算结果为12-345,因此预期的捕获组1 实际上是捕获组112,它不存在。请参阅下面的第二次尝试说明:

"(\(BRP-)($pic)(-.{15}\))":

  • 捕获组 1:(BRP-
  • 捕获组 2:01-001
  • 捕获组 3:-06K48b-SC-CC-01)

"`$1$change`$3" 在运行时变为$112-345$3,然后变为$112-345-06K48b-SC-CC-01)。请注意,$112 在捕获组被替换之前已被插入。然后检查捕获组112。由于它不存在,$112 只是假设为一个字符串。

【讨论】:

  • 感谢您的解决方案和解释;这正是我需要学习的。
【解决方案2】:

以下可能是您所追求的,

$pic = "01-001"
$change = "12-345"
$RenameFiles_FilterStr = "*BRP-$pic*.tif"

gci $RenameFiles_FilterStr -recurse | % { $_.BaseName -replace $pic,$change }

# The above returns renamed strings (files not renamed yet). If the expected result matches the returned ones, then uncomment the below and run to rename the files
# gci $RenameFiles_FilterStr -recurse | % { Rename-Item -NewName ($_.BaseName -replace $pic,$change) }

【讨论】:

  • 谢谢。虽然我正在处理的实际问题更复杂,需要正则表达式替换的灵活性,但我真的很喜欢您提供的简洁解决方案(因为它解决了我提出的问题)。有很多次我可以使用像你这样的更简单的解决方案,我预计在我当前的项目之外的未来我会经常找到它的用途。它的简洁真的很优雅
猜你喜欢
  • 2013-01-25
  • 1970-01-01
  • 2012-06-20
  • 2016-02-13
  • 2012-08-26
  • 2012-08-01
  • 1970-01-01
  • 2021-10-13
  • 1970-01-01
相关资源
最近更新 更多