字符串匹配后替换接下来的两行
Replace next two lines after string match
我目前正在编写一个脚本,该脚本应根据用户的选择在匹配字符串后替换文件中的两行。
我要编辑的文件如下所示:
[default]
string_a=sadasdasdas
string_b=dasdasdasdas
[profile1]
string_a=xxxxxx
string_b=xsaassaasas
[profile2]
string_a=yyyyyyy
string_b=yaayayayaya
我总是想在 [default] 之后覆盖 string_a & string_b。
请注意,[default] 也可能位于文件的最底部,因此我不能只计算行数然后静态地进行计算。
用户可以在(在这种情况下)配置文件 1 和配置文件 2 之间进行选择。在选择配置文件 2 之后,配置文件 2 的 string_a 和 string_b 应该替换为 string_a & 默认值 string_b。
我现在的代码是这样的:
$filePath = './credentials'
$fileContent = Get-Content $filePath
$profiles = [regex]::Matches($fileContent, '\[(.*?)\]') |ForEach-Object { $_.Groups[1].Value }
Write-Host "Following profiles found: "
for ($i=0; $i -lt $profiles.length; $i++){
Write-Host $i"." $profiles[$i]
}
$userInput = Read-Host "Which profile set to default? "
Write-Host $profiles[$userInput]
$fileContent | Select-String $profiles[$userInput] -Context 1,2 | ForEach-Object {
$stringA = $_.Context.PostContext[0]
$stringB = $_.Context.PostContext[1]
#At this point I have access to the both string´s I want to replace the string´s of the default profile
# I could do this, but then I still have the old lines in the file...
# So the following code is not an option.
$NewContent = Get-Content -Path $filePath |
ForEach-Object {
# Output the existing line to pipeline in any case
$_
# If line matches regex
if($_ -match ('^' + [regex]::Escape('[default]')))
{
# Add output additional line
$stringA
$stringB
}
}
# Write content of $NewContent varibale back to file
$NewContent | Out-File -FilePath $filePath -Encoding Default -Force
}
示例输出文件,以防用户选择 profile1 作为新的默认值
[default]
string_a=xxxxxx
string_b=xsaassaasas
[profile1]
string_a=xxxxxx
string_b=xsaassaasas
[profile2]
string_a=yyyyyyy
string_b=yaayayayaya
希望这不是很明显,但由于这是我的第一个真正的 powershell 脚本,我还没有找到解决我的问题的方法。
任何帮助都会很棒!
谢谢
示例:
# This is sample data
$lines = @(@'
[default]
string_a=sadasdasdas
string_b=dasdasdasdas
[profile1]
string_a=xxxxxx
string_b=xsaassaasas
[profile2]
string_a=yyyyyyy
string_b=yaayayayaya
'@ -split "`r`n")
# In real world use:
# $encoding = [System.Text.Encoding]::ASCII
# $lines = [System.IO.File]::ReadAllLines($path, $encoding)
#Read file
$lines = $lines | ForEach-Object { $_.Trim()} # Trim spaces
$sections = @{}
$currentSection = $null
$hasErrors = $false
$lines | ForEach-Object {
if ([String]::IsNullOrWhiteSpace($_)) {
#ignore
} elseif ($_.StartsWith('[') -and $_.EndsWith(']') ) {
$currentSection = $_.Substring($_.IndexOf('[') + 1, $_.LastIndexOf(']') - 1)
$sections[$currentSection] = @{}
} elseif ($sections.ContainsKey($currentSection)) {
$PVPair = [String[]]$_.Split('=',2)
if ($PVPair.Count -eq 2) {
$sections[$currentSection][$PVPair[0]] = $PVPair[1]
} else {
Write-Warning -Message "Wrong line format [$($_)]"
$hasErrors = $true
}
} else {
Write-Warning -Message "Unexpected behaviour on section $currentSection, line $($_)"
$hasErrors = $true
}
}
if ($hasErrors) {
Write-Error -Message 'Errors occured'
return
}
# Choice
$choice = $null
$choiceVariants = @($sections.Keys | Where-Object { $_ -ne 'default' })
while ($choiceVariants -notcontains $choice) {
Write-Host "Choose between $($choiceVariants -join ',')"
$choice = $choiceVariants | Out-GridView -Title 'Choose variant' -OutputMode Single
#Alternative: $choice = Read-Host -Prompt "Your choice"
}
Write-Host -ForegroundColor Yellow "You choose $($choice)"
# Change
$sections[$choice]['string_a'] = $sections['default']['string_a']
$sections[$choice]['string_b'] = 'newXSAA'
# Output
$outputLines = $sections.Keys | ForEach-Object {
$sectionName = $_
Write-Output "[$sectionName]"
$sections[$sectionName].Keys | ForEach-Object {
Write-Output "$_=$($sections[$sectionName][$_])"
}
}
# This is sample output
$outputLines | % { Write-Host $_ -f Magenta }
# In Real world:
# [System.IO.File]::WriteAllLines($path, $outputLines, $encoding)
我目前正在编写一个脚本,该脚本应根据用户的选择在匹配字符串后替换文件中的两行。
我要编辑的文件如下所示:
[default]
string_a=sadasdasdas
string_b=dasdasdasdas
[profile1]
string_a=xxxxxx
string_b=xsaassaasas
[profile2]
string_a=yyyyyyy
string_b=yaayayayaya
我总是想在 [default] 之后覆盖 string_a & string_b。 请注意,[default] 也可能位于文件的最底部,因此我不能只计算行数然后静态地进行计算。
用户可以在(在这种情况下)配置文件 1 和配置文件 2 之间进行选择。在选择配置文件 2 之后,配置文件 2 的 string_a 和 string_b 应该替换为 string_a & 默认值 string_b。
我现在的代码是这样的:
$filePath = './credentials'
$fileContent = Get-Content $filePath
$profiles = [regex]::Matches($fileContent, '\[(.*?)\]') |ForEach-Object { $_.Groups[1].Value }
Write-Host "Following profiles found: "
for ($i=0; $i -lt $profiles.length; $i++){
Write-Host $i"." $profiles[$i]
}
$userInput = Read-Host "Which profile set to default? "
Write-Host $profiles[$userInput]
$fileContent | Select-String $profiles[$userInput] -Context 1,2 | ForEach-Object {
$stringA = $_.Context.PostContext[0]
$stringB = $_.Context.PostContext[1]
#At this point I have access to the both string´s I want to replace the string´s of the default profile
# I could do this, but then I still have the old lines in the file...
# So the following code is not an option.
$NewContent = Get-Content -Path $filePath |
ForEach-Object {
# Output the existing line to pipeline in any case
$_
# If line matches regex
if($_ -match ('^' + [regex]::Escape('[default]')))
{
# Add output additional line
$stringA
$stringB
}
}
# Write content of $NewContent varibale back to file
$NewContent | Out-File -FilePath $filePath -Encoding Default -Force
}
示例输出文件,以防用户选择 profile1 作为新的默认值
[default]
string_a=xxxxxx
string_b=xsaassaasas
[profile1]
string_a=xxxxxx
string_b=xsaassaasas
[profile2]
string_a=yyyyyyy
string_b=yaayayayaya
希望这不是很明显,但由于这是我的第一个真正的 powershell 脚本,我还没有找到解决我的问题的方法。
任何帮助都会很棒!
谢谢
示例:
# This is sample data
$lines = @(@'
[default]
string_a=sadasdasdas
string_b=dasdasdasdas
[profile1]
string_a=xxxxxx
string_b=xsaassaasas
[profile2]
string_a=yyyyyyy
string_b=yaayayayaya
'@ -split "`r`n")
# In real world use:
# $encoding = [System.Text.Encoding]::ASCII
# $lines = [System.IO.File]::ReadAllLines($path, $encoding)
#Read file
$lines = $lines | ForEach-Object { $_.Trim()} # Trim spaces
$sections = @{}
$currentSection = $null
$hasErrors = $false
$lines | ForEach-Object {
if ([String]::IsNullOrWhiteSpace($_)) {
#ignore
} elseif ($_.StartsWith('[') -and $_.EndsWith(']') ) {
$currentSection = $_.Substring($_.IndexOf('[') + 1, $_.LastIndexOf(']') - 1)
$sections[$currentSection] = @{}
} elseif ($sections.ContainsKey($currentSection)) {
$PVPair = [String[]]$_.Split('=',2)
if ($PVPair.Count -eq 2) {
$sections[$currentSection][$PVPair[0]] = $PVPair[1]
} else {
Write-Warning -Message "Wrong line format [$($_)]"
$hasErrors = $true
}
} else {
Write-Warning -Message "Unexpected behaviour on section $currentSection, line $($_)"
$hasErrors = $true
}
}
if ($hasErrors) {
Write-Error -Message 'Errors occured'
return
}
# Choice
$choice = $null
$choiceVariants = @($sections.Keys | Where-Object { $_ -ne 'default' })
while ($choiceVariants -notcontains $choice) {
Write-Host "Choose between $($choiceVariants -join ',')"
$choice = $choiceVariants | Out-GridView -Title 'Choose variant' -OutputMode Single
#Alternative: $choice = Read-Host -Prompt "Your choice"
}
Write-Host -ForegroundColor Yellow "You choose $($choice)"
# Change
$sections[$choice]['string_a'] = $sections['default']['string_a']
$sections[$choice]['string_b'] = 'newXSAA'
# Output
$outputLines = $sections.Keys | ForEach-Object {
$sectionName = $_
Write-Output "[$sectionName]"
$sections[$sectionName].Keys | ForEach-Object {
Write-Output "$_=$($sections[$sectionName][$_])"
}
}
# This is sample output
$outputLines | % { Write-Host $_ -f Magenta }
# In Real world:
# [System.IO.File]::WriteAllLines($path, $outputLines, $encoding)