因此,对于这个脚本,如果我多次运行该脚本,它会用我需要保持不变的替换文本“start-sleep -s 30”覆盖第二次出现的“start-sleep -s 10” IE。 “开始睡眠-s 10”。当我对此进行测试时,它运行一次时效果很好,但如果脚本运行多次怎么办?在测试期间,当脚本运行不止一次时,当我需要它在每次运行脚本时保持“start-sleep -s 10”时,第二个实例就会更改为“start-sleep -s 30”以及不更改文件的其余部分。 PS中有没有办法防止这种情况?例如,可能只有脚本搜索行 0-115?因为 start-sleep -s 10 的第二个实例位于第 145 行。我基本上需要的是脚本找到“start-sleep -s 10”的第一个实例并替换为“start-sleep -s 30” ,每次我运行这个脚本时,不要管“start-sleep -s 10”的第二个实例。我之前为此发布了一个原始问题,可以在本文末尾添加。
$ScriptPath = "C:\ScriptsFolder\powershell.ps1"
$newContent = switch -Wildcard -File $ScriptPath {
# if this line contains `Start-Sleep -s 10`
'*Start-Sleep -s 10*' {
# if we previously matched this
if($skip) {
# output this line
$_
# and skip below logic
continue
}
# if we didn't match this before (if `$skip` doesn't exist)
# replace from this line `Start-Sleep -s 10` for `Start-Sleep -s 30`
$_.Replace('Start-Sleep -s 10', 'Start-Sleep -s 30')
# and set this variable to `$true` for future matches
$skip = $true
}
# if above condition was not met
Default {
# output this line as-is, don't change anything
$_
}
}
$newContent | Set-Content $ScriptPath
原始问题:我需要在 PowerShell 脚本中查找并替换一个字符串的出现(脚本大约 250 行长)。脚本中出现了两次字符串“start-sleep -s 10”。我需要编辑并且只将第一次出现更改为“start-sleep -s 30”并保留第二次出现“start-sleep -s 10”。我遇到的问题是我有几个脚本变体进行编辑,因此我的方法是找到第一次出现的行的范围,进行更改,然后保存脚本并保持其他所有内容不变。对于 PowerShell 来说是新的,所以不知道该怎么做。我一直在看关于如何使用 Get-Content 和 Set-Content 查找和替换文件中的文本的在线文章,但我需要更改“start-sleep -s 10”的第一个出现并保持第二个不变。
回答1
要仅替换一定数量的匹配项,您可以使用 https://docs.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex.replace?view=net-6.0#system-text-regularexpressions-regex-replace(system-string-system-string-system-int32),它允许您指定替换的数量
$scriptPath = '.\sleep_text.txt'
$scriptContent = Get-Content $scriptPath -Raw
$find = 'start-sleep -s 10'
$replacement = 'start-sleep -s 30'
$numberOfReplacements = 1
$regex = [regex]$find
$regex.Replace( $scriptContent, $replacement, $numberOfReplacements ) | Set-Content -Path $scriptPath
不处理同一个文件两次
我同意 Theo 的评论,如果您不想两次处理同一个文件,那么只需将文件保存到不同的位置或在预处理期间可以过滤掉的不同名称。如果您不喜欢这种方法,您可以使用的另一种方法是为您的脚本提供一种不同的方式来了解哪些文件已被处理。
这是一种方式的示例。在这里,我们在处理过程中将注释附加到脚本的底部。该脚本在 if 语句中查找此注释,如果找到则仅在屏幕上显示该文件已被处理而不是再次处理的警告。
$scriptPath = '.\sleep_text.txt'
$scriptContent = Get-Content $scriptPath -Raw
if ($scriptContent -notmatch '# processed') {
$find = 'start-sleep -s 10'
$replacement = 'start-sleep -s 30'
$numberOfReplacements = 1
$regex = [regex]$find
($regex.Replace( $scriptContent, $replacement, $numberOfReplacements )) + "`n# processed" | Set-Content -Path $scriptPath
}
else {
Write-Warning "$scriptPath already processed"
}
WARNING: .\sleep_text.txt already processed