1

我正在整理一个简单的 PowerShell 脚本,它将查找/替换各种数量的关键字。如果找到关键字,则应将其替换为不同的短语。

这适用于存在关键字的行,但是脚本正在删除不存在关键字的行;这不是我想要的行为。

我的期望是它将取代 KEYWORDS 并保持其他所有内容不变。

脚本:

#*=============================================
#* Script Name: SQLFILE_find_and_replace.ps1
#* Created: 12-Jun-2013
#*=============================================
#* Purpose: Intended for SQLFILE scripts
#* generated from a datapump dump file.
#*
#* Will find and replace "Create [Keyword]"
#* with "Create or Replace [Keyword]" within a
#* specified file.
#*=============================================

#Keywords for find/replace to act on; adjust as necessary.
$KEYWORDS = @("PROCEDURE","PACKAGE","FUNCTION","TYPE","SEQUENCE","VIEW","DATABASE LINK","TRIGGER")

# Get-FileName from http://blogs.technet.com/b/heyscriptingguy/archive/2009/09/01/hey-scripting-guy-september-1.aspx
Function Get-FileName($initialDirectory)
{
    [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") |
    Out-Null

    $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
    $OpenFileDialog.initialDirectory = $initialDirectory
    $OpenFileDialog.filter = "All files (*.*)| *.*"
    $OpenFileDialog.ShowDialog() | Out-Null
    $OpenFileDialog.filename
} #end function Get-FileName

#Ask user for file
$FILENAMELOC=Get-FileName -initialDirectory "C:\"


Write-Progress -Activity "Loading file" -status "$FILENAMELOC" -percentComplete 0

$file = (Get-Content -Path $FILENAMELOC)
$lines =  ($file | Measure-Object)
$lineprocessed = 0

$file |
    ForEach-Object {
        $lineprocessed = $lineprocessed + 1
        ForEach ($KEYWORD in $KEYWORDS) {
            if ($_.indexof("$KEYWORD") -ge 0) {
                if ($KEYWORD -eq "SEQUENCE" -and $_.indexof("MINVALUE") -ge 0) {
                    $SEQUENCENAME = $_.Substring($_.indexof("$KEYWORD"),$_.indexof("MINVALUE")-$_.indexof("$KEYWORD")-1)
                    $DROP = "DROP "+$SEQUENCENAME +";"
                    $CREATE = "CREATE "+$SEQUENCENAME +";"
                    $SQL = $DROP+"`r`n"+$CREATE
                    $_ -replace "CREATE $KEYWORD", $SQL
                }
                else {
                    $_ -replace "CREATE $KEYWORD", "CREATE OR REPLACE $KEYWORD"
                }
            }
        }
        Write-Progress -Activity "Replacing keywords" -status "Running" -percentComplete ([System.Math]::Round((($lineprocessed / $lines.count)*100),2))
    } |
    Set-Content $FILENAMELOC

测试文件:

This is a test.
CREATE PROCEDURE Blah
CREATE TRIGGER Boblawbla
CREATE FUNCTION
This is another test

Watch me disappear.

结果:

CREATE OR REPLACE PROCEDURE Blah
CREATE OR REPLACE TRIGGER Boblawbla
CREATE OR REPLACE FUNCTION

这是一个 Windows 7 盒子。

4

1 回答 1

2

这是你的罪魁祸首:

if ($_.indexof("$KEYWORD") -ge 0) {
  if ($KEYWORD -eq "SEQUENCE" -and $_.indexof("MINVALUE") -ge 0) {
    ...
    $_ -replace "CREATE $KEYWORD", $SQL
  } else {
    $_ -replace "CREATE $KEYWORD", "CREATE OR REPLACE $KEYWORD"
  }
}

只有 2$_ -replace ...产生管道重定向到的输出Set-Content。您似乎假设-replace操作员修改了内容$_并将Write-Host $_该行回显到管道中。两者都不是这样。$_ -replace ...从 中获取值$_,替换它找到的匹配项,并将修改后的字符串写入 STDOUT。Write-Host将消息写入控制台,而不是 STDOUT。

添加一个else分支来回显不包含任何关键字的行,你应该没问题:

if ($_.indexof("$KEYWORD") -ge 0) {
  if ($KEYWORD -eq "SEQUENCE" -and $_.indexof("MINVALUE") -ge 0) {
    ...
    $_ -replace "CREATE $KEYWORD", $SQL
  } else {
    $_ -replace "CREATE $KEYWORD", "CREATE OR REPLACE $KEYWORD"
  }
} else {
  $_
}

不过,你让这种方式太复杂了。这样的事情就足够了(如果我正确解析了您的代码):

(Get-Content $FILENAMELOC) | % {
  $_ -replace 'CREATE SEQUENCE (\S*)', "DROP `$1;`r`nCREATE `$1" `
     -replace 'CREATE (PROCEDURE|PACKAGE|FUNCTION|TYPE|VIEW|DATABASE LINK|TRIGGER)', 'CREATE OR REPLACE $1'
} | Set-Content $FILENAMELOC
于 2013-06-28T20:10:00.927 回答