在大型文件中查找和替换

时间:2010-05-06 19:27:50

标签: powershell

我想在大型xml文件中找到一段文本,并希望替换为其他一些文本。文件大小约为(50GB)。我想在命令行中执行此操作。我正在看Powershell并想知道它是否可以处理大尺寸。另外我想知道在PowerShell中转义关键运算符的语法。我是PowerShell新手

目前我正在尝试这样的事情,但它不喜欢它

    Get-Content C:\File1.xml | Foreach-Object {$_ -replace "xmlns:xsi=\"http:\/\/www\.w3\.org\/2001\/XMLSchema-instance\"", ""} | Set-Content C:\File1.xml

我要替换的文字是 xmlns:xsi =“http://www.w3.org/2001/XMLSchema-instance”,带有空字符串“”。

问题

  1. powerShell可以处理大 文件
  2. 我怎么称呼 来自命令行的powershell脚本
  3. 转义键的语法 powerShell中的运算符和列表 powerShell中的关键运算符。
  4. 我不希望替换发生在 内存和偏好流媒体假设 这将不会带来服务器 它的膝盖。
  5. 我可以采取其他任何方法(不同 工具/策略?)
  6. 由于

5 个答案:

答案 0 :(得分:11)

我有类似的需求(以及类似的缺乏PowerShell经验),但是从这个页面上的其他答案拼凑出一个完整的答案加上更多的研究。

我也想避免正则表达式处理,因为我也不需要它 - 只是一个简单的字符串替换 - 但是在一个大文件上,所以我不希望它加载到内存中。

这是我使用的命令(为可读性添加换行符):

Get-Content sourcefile.txt
    | Foreach-Object {$_.Replace('http://example.com', 'http://another.example.com')}
    | Set-Content result.txt

工作完美!从来没有吸过太多内存(很明显没有将整个文件加载到内存中),只需要几分钟就可以完成。

答案 1 :(得分:4)

它不喜欢它,因为您无法从文件中读取并使用Get-Content / Set-Content同时回写它。我建议使用临时文件,然后在最后,将file1.xml重命名为file1.xml.bak,并将临时文件重命名为file1.xml。

  1. 是,只要您不尝试一次加载整个文件。逐行将工作,但会有点慢。使用-ReadCount参数并将其设置为1000以提高性能。
  2. 哪个命令行?电源外壳?如果是这样,那么您可以像.\myscript.ps1那样调用您的脚本,如果需要参数c:\users\joe\myscript.ps1 c:\temp\file1.xml
  3. 一般来说,对于正则表达式,如果您不需要引用PowerShell变量,我会使用单引号。然后你只需要担心正则表达式转义而不是PowerShell转义。如果你需要使用双引号,那么反向刻度字符是双引号中的转义字符,例如“`$ p1设置为$ ps1”。在您的示例中,单引号简化了正则表达式(注意:正斜杠不是正则表达式中的元字符):

    '的xmlns:的xsi = “http://www.w3.org/2001/XMLSchema-instance”'

  4. 你绝对想要传输这个,因为50GB不适合内存。但是,如果您逐行处理,则会出现问题。如果要替换的文本分为多行,该怎么办?

  5. 如果您没有分割线问题,那么我认为PowerShell可以解决此问题。

答案 2 :(得分:3)

除了担心分块读取文件以避免将文件加载到内存中外,您还需要经常转储到磁盘上,以免将生成的文件的全部内容存储在内存中。

Get-Content sourcefile.txt -ReadCount 10000 | 
    Foreach-Object {
        $line = $_.Replace('http://example.com', 'http://another.example.com')
        Add-Content -Path result.txt -Value $line
    }

-ReadCount <number>设置一次读取的行数。然后ForEach-Object在读取时写入每一行。对于填充有SQL插入的30GB文件,我的内存大约为200MB,CPU容量为8%。同时,在我杀死它之前,将它们全部传送到Set-Content,达到3GB的内存。

答案 3 :(得分:0)

这是我的看法,基于其他一些答案:

Function ReplaceTextIn-File{
  Param(
    $infile,
    $outfile,
    $find,
    $replace
  )

  if( -Not $outfile)
  {
    $outfile = $infile
  }

  $temp_out_file = "$outfile.temp"

  Get-Content $infile | Foreach-Object {$_.Replace($find, $replace)} | Set-Content $temp_out_file

  if( Test-Path $outfile)
  {
    Remove-Item $outfile
  }

  Move-Item $temp_out_file $outfile
}

并且这样称呼:

ReplaceTextIn-File -infile "c:\input.txt" -find 'http://example.com' -replace 'http://another.example.com' 

答案 4 :(得分:-1)

powershell字符串中的转义字符是反引号(`),而不是反斜杠(\)。我举个例子,但wiki标记也使用了反引号。 :(

你应该逃脱的唯一一件事是报价 - 期限等等应该没有。