如果单词退出则删除行并在powershell中打印具有两个单词的行之间的所有行

时间:2014-02-10 14:07:33

标签: batch-file powershell

问题1:

我有一个MAIN.txt文件,包含2,000,000行。文件将采用以下格式

  

单元= 123
  XXX
  YYY

     

单元= 245
  XX
  是的

     

单位= PO 789
  X
  ÿ

     

单元= 258
  XY
  yx

     

单元777 =
  XZ
  zx

     

单元= 999
  YZ
  zy

     

单元= 456
  ZZ
  是的

我想删除包含“PO”字样的行以及跟随它们的三行。

示例输出:

  

单元= 123
  XXX
  yyy

     

单元= 245
  XX
  YY

     

单元= 258
  XY
  yx

     

单元777 =
  XZ
  zx

     

单元= 999
  YZ
  zy

     

单元= 456
  ZZ
  是的

我是Powershell的新手。我尝试了这个,但我只能删除PO的行。如何删除后面的n行。

第二个问题:

我有一个文件,比如extractthis.txt -

  

123 | 258

     

777 | 456

我想在MAIN文件中打印出数字为123的行和258之后的两行(即bbb),并将其保存在一个新文件中,比如file1。

然后从extractthis.txt(777 | n456)读取第二行,并在具有数字777的行和具有456(jjj)的行之后的两行之间打印行,并将其保存到file2.txt,依此类推。

我在Unix中做过类似的事情。但我正在努力在Powershell中做同样的事情。

2 个答案:

答案 0 :(得分:1)

对于问题#1,类似以下函数的东西应该可以工作(至少在我对你的数据文件进行尝试时它会这样做):

function Skip-Match {
[cmdletbinding()]
    Param(
        [parameter(Mandatory)][string]$Pattern,
        [parameter(Mandatory)][string]$Path,
        [int]$Count=3
    )

    $lines = Get-Content -Path $Path
    $state = -1
    $lines | ForEach-Object {
        $line = $_
        if( $line.ToString() -like "*$Pattern*" ) {
            $state=3
        } elseif ( $state -lt 0 ) {
            $line
            Write-Verbose $line
        }
        $state--
    }
}

然后,您可以将其保存到文件(我称之为skip-match.ps1),获取文件,然后执行该功能......类似于:

. .\skip-match.ps1
Skip-Match -Pattern "PO" -Path .\datafile.dat

答案 1 :(得分:1)

鉴于你在MAIN.txt中有如此多的行,我会避免使用Get-Content,因为它会将整个文件打开到内存中。改用流。

function sanitise($file) {

    $reader = [System.IO.File]::OpenText($file)
    $i = 0
    try {
        while(($line = $reader.ReadLine()) -ne $null) {
            if($i -gt 0) { $i++ }
            if($i -gt 4) { $i = 0 }
            if($line -like "*PO*") { $i++ }
            if ($i -eq 0) { echo $line }
        }
    }
    finally {
        $reader.Close()
    }
}

function readBetweenLines($file, $a, $b) {

    $reader = [System.IO.File]::OpenText($file)
    $i = 0
    $read = $false
    try {
        while(($line = $reader.ReadLine()) -ne $null) {
            if($i -gt 0) { $i++ }
            if($line -match ".*$a`$") { $read = $true }
            if($line -match ".*$b`$") { $i++ }          
            if(($read) -and ($i -lt 4)) { echo $line }
            if($i -gt 4) { break }
        }
    }
    finally {
        $reader.Close()
    }
}

sanitise(".\MAIN.txt")

$extract = get-content ".\extractthis.txt"
foreach($line in $extract) {
    $lineNum = $line.split("|")
    readBetweenLines ".\MAIN.txt" $lineNum[0] $lineNum[1]
}

echo语句替换为您在其他地方输出内容所需的任何内容。就目前而言,这还需要您在运行行检查功能之前将MAIN.txt清理为新文件。