我之前从未使用过PowerShell,Google也没有给出我所需要的答案。我希望你们能帮助我。 我需要找到目录中的所有文件(包括子目录),这些文件有两行:
aaa aaa
bbb bbb
并将第二行替换为ccc
如果bbb bbb
之后没有排aaa aaa
行,则不应该进行替换。
这是我到目前为止所拥有的:
$line3 = "aaa[ ]*aaa[ ]*bbb[ ]*bbb"
Get-ChildItem -exclude *.bak -recurse *.txt | Where-Object {$_.Attributes -ne "Directory"} |
ForEach-Object {
Copy-Item $_ "$($_).bak";
$wholeFile = [IO.File]::ReadAllText("$_");
$wholeFile = $wholeFile.replace("`n", " ");
$wholeFile = $wholeFile.replace("`r", " ");
$temp3 = $wholeFile | Select-String -pattern $line3 -quiet;
if(($temp3 -eq "True")){
(Get-Content $_) -replace "bbb[ ]*bbb", "ccc" | Set-Content -path $_;
}
else{
echo failed
}
}
我认为这个代码几乎可以工作,除非文件有2次出现“bbb bbb”:一个紧跟在“aaa aaa”之后,另一个没有“aaa aaa”。两条线都会被替换,我只需要更换第一条线。有什么方法可以解决它吗? 有经验的人可以告诉我,如果我错过了什么吗?我需要什么更简单/更短的解决方案?我在powershell中看到了很多简洁的单行解决方案。我的案子有什么类似的吗? 感谢
答案 0 :(得分:2)
这是一个批处理解决方案:)
@echo off
setlocal enabledelayedexpansion
cd C:\folder
set aaa=false
for /r C:\folder %%a in (*) do (
for /f "tokens=1,2 delims= " %%x in (%%a) do (
if "!aaa!"=="true" (
if "%%x"=="bbb" if "%%y"=="bbb" (
echo ccc ccc >>temp.txt
del %%a /f /q
ren temp.txt %%~nxa
set aaa=false
)
) else (
if "%%x"=="aaa" if "%%y"=="aaa" set aaa=true
echo %%x %%y >>temp.txt
)
)
)
答案 1 :(得分:1)
我认为这会做你想要的。这不是一个单行,我相信它可以简化。不过,我更担心得到一些功能。
我也测试了你的用例。当它直接跟随'aaa aaa'线时,这将只替换'bbb bbb'线。具有该行的文件中的所有其他位置都不会被覆盖。
只需修改顶部的变量以及您的测试信息。
我一直以为你会:
#script variables
$filePath = 'C:\Temp\SO\'
$processFiles = Get-ChildItem -Exclude *.bak -Filter *.txt -Recurse -Path $filePath
$query = 'aaa aaa'
$query2 = 'bbb bbb'
$replace = 'ccc'
#script begin
foreach ( $file in $processFiles ) {
#Pre-Processing | backup the file for archival
$file | Copy-Item -Destination "$file.bak"
$arrayData = Get-Content $file
for ($i=0; $i -lt $arrayData.Count; $i++)
{
if ( $arrayData[$i] -match $query ) {
if ( $arrayData[$i+1] -match $query2 ) {
$arrayData[$i+1] = $arrayData[$i+1].Replace($query2,$replace)
}
else {
#Catch if the second query isn't matched.
}
}
else {
#Catch if the first query isn't matched.
}
}
#Overwrites the original text file that was being processed
$arrayData | Out-File $file -Force
}
答案 2 :(得分:0)
这是一个单线解决方案:
$a="aaa aaa";$b="bbb bbb";$c="ccc";ls *.txt -File -Recurse|foreach{$l=0;cp $_ "$($_).bak";(cat $_)|foreach{if($_ -match $a){$l=1;$_}else{if($_ -match $b){if($l -eq 1){$_ -replace($b,$c)}else{$_};$l=2}else{$l=0;$_}}}|sc($_) -Force}
这有点模糊,我不会称之为“整洁”,但它确实有效。