Powershell文本操作



我正在尝试生成一个经过整理的文本文件。使用一个实用程序,我可以列出好的和坏的媒体文件。我想提取一个坏媒体文件的列表,这样我就可以替换它们了。

在日志中,坏媒体文件如下所示。

Testing L:MUSIC--Finnegan's Wake.mp3...
First frame invalid
MPEG 2.0 Layer I, 16000 hz, Stereo, Crc: No, Length: 0:00
Invalid bytes at end: 4622724
Frames: 0
Errors: 1 (100.00%)
-- NOT OK -- 

好的文件在日志中是这样的。

Testing L:MUSIC80's Giga Hits Collection. Only Best Disco Hits (2013) - SMG1383. William Pitt - City Lights (Extended).mp3...
ID3v1 found: City Lights (Extended) (William Pitt / Euro Disco 80's)
ID3v2 found: 73205 Bytes
MPEG 1.0 Layer III, 320 kbit, 44100 hz, Stereo, Crc: No, Length: 5:10
Frames: 11831
-- Ok --

我正试图提取术语-- Not Ok --

使用ps命令

(Get-Content "c:workingMP3Test.log") -notmatch "-- Not Ok --" | Out-File "c:workingBad.txt"

它仍然返回所有歌曲,但没有-- Ok --

我只想以--Not Ok-- 的歌曲标题结束

我认为你可能需要一个脚本来完成这项工作,因为你需要匹配最后一行,但你需要写块的第一行。这似乎很有效。

$curFile="";
foreach ($line in gc c:workingMP3Test.log){
    if ($line.StartsWith("Testing ")){
        $curFile = $line.Replace("Testing ","")     
    }
    elseif ($line.StartsWith("-- NOT OK --")){
        Write-Output $curFile
    }
}

您需要将Get-Content的输出通过管道传输到where cmdlet中,例如:

Get-Content 'c:workingMP3Test.log' | ? {$_ -notmatch '-- Not Ok --'} | Out-File 'c:workingBad.txt'

最好还是使用Select-String cmdlet,因为它会更快:

Select-String  'c:workingMP3Test.log' -Pattern '-- Not Ok --' | Select -ExpandProperty line | Out-File 'c:workingBad.txt'

选择Sting将是实现这一目标的方法。特别是-Context参数

捕获匹配行前后指定数量的行。

select-string "C:temptest.txt"  -Pattern "-- NOT OK --" -SimpleMatch -Context 6,0).Context.Precontext

这将在比赛前返回6行。至少使用PowerShell 3.0,我们使用.Context.Precontext仅从MatchInfo对象获取原始文本。

如果文件中有多个匹配项,则可能需要进行更多的后期处理。

Select-String支持正则表达式,我们在这里使用的是而不是。为了确保将来不会出现意外匹配,您可以使用-SimpleMatch。请说明此特定实例不需要它。

为了只匹配该块中的歌曲,我们可以进行一些后期处理

$result = (select-string C:temptest.txt  -Pattern "-- NOT OK --" -SimpleMatch -Context 6,0).Context.Precontext 
$result | where-object{$_ -match "Testing"} | ForEach-Object{$_ -replace "^testing (.*?).*$",'$1'}

在匹配的行中,我们选择与"测试"匹配的行。然后,使用regex,我们删除测试前缀和尾部句点。当然,这不是唯一的方法。

最新更新