如何在特定行数后插入行文本

时间:2017-12-02 10:23:16

标签: powershell

我已经逐行阅读。

foreach($line in [System.IO.File]::ReadLines("C:\temp\test.txt"))
{
    $line
}

结果:

  

(1,1,1,42.48333330,1.46666670,N'Aixàs'),
  (2,1,1,42,46666670,1.50000000,N'Aixirivali'),
  (3,1,1,42.46666670,1.50000000,N'Aixirivall'),
  (4,1,1,42.46666670,1.50000000,N'Aixirvall'),
  (5,1,1,42.46666670,1.48333330,N'Aixovall'),
  (6,2,1,42.50000000,1.51666670,N'Andorra'),
  (7,2,1,42.50000000,1.51666670,N'Andorra la Vella'),
  (8,2,1,42.50000000,1.51666670,N'Andorra-Vieille'),
  (9,2,1,42.50000000,1.51666670,N'Andorre'),
  (10,2,1,42.50000000,1.51666670,N'Andorre-la-Vieille'),

我现在需要做的就是每隔900行删除一次逗号,每隔900行删除一次以插入文本行(“INSERT INTO”)。应该是这样的(每第5行的例子):

  

INSERT INTO DBname(id1,id2,id3,long,lat,[name])VALUES
  (1,1,1,42.48333330,1.46666670,N'Aixàs'),
  (2,1,1,42,46666670,1.50000000,N'Aixirivali'),
  (3,1,1,42.46666670,1.50000000,N'Aixirivall'),
  (4,1,1,42.46666670,1.50000000,N'Aixirvall'),
  (5,1,1,42.46666670,1.48333330,N'Aixovall')

     

INSERT INTO DBname(id1,id2,id3,long,lat,[name])VALUES
  (6,2,1,42.50000000,1.51666670,N'Andorra'),
  (7,2,1,42.50000000,1.51666670,N'Andorra la Vella'),
  (8,2,1,42.50000000,1.51666670,N'Andorra-Vieille'),
  (9,2,1,42.50000000,1.51666670,N'Andorre'),
  (10,2,1,42.50000000,1.51666670,N'Andorre-la-Vieille')

     

依旧......

我应该在foreach中引入另一个循环吗?我希望你的导游达到我想要的目的。

4 个答案:

答案 0 :(得分:0)

这似乎难以用语言解释。所以我正在使用代码。您可以根据需要将偏移值更改为900.

$File = Get-Content .\Test.txt
$length = $File.Count
$offset = 5
$i = $offset
do
{
    $Line = $File[$i-1].Substring(0, $File[$i-1].LastIndexOf(","))
    $InsertLine = "INSERT INTO DBname (id1, id2, id3, long, lat, [name]) VALUES"

$NewData = "$Line

$InsertLine"

    $File[$i-1] = $NewData
    $i = $i+$offset
}
While ($i -le $length)
$File

答案 1 :(得分:0)

File.ReadLines Method返回字符串

  

返回值
类型:System.Collections.Generic.IEnumerable<String>所有   文件的行,或查询结果的行。

示例

PS D:\PShell> $x = [System.IO.File]::ReadLines($File)

PS D:\PShell> $x.GetType() | Format-Table -AutoSize

IsPublic IsSerial Name              BaseType                           
-------- -------- ----              --------                           
False    False    ReadLinesIterator System.IO.Iterator`1[System.String]

应用于您的示例的以下代码剪辑应该可以完成这项工作。 (假设每行中没有空行和尾随逗号,包括最后一行。)

$index = 4            # change to match your demand
$lines = [System.IO.File]::ReadLines("C:\temp\test.txt") -split [System.Environment]::NewLine
$insert = 'INSERT INTO DBname (id1, id2, id3, long, lat, [name]) VALUES '

$insert
for ( $i=0; $i -lt $lines.Count; $i++ ) {
    if ( $i -gt 0 -and ( ( ($i + 1) % $index ) -eq 0 
                       ) -or ( $i -eq $lines.Count - 1 ) ) 
    {
        $lines[$i].Substring(0, $lines[$i].LastIndexOf(","))
        if ( $i -lt $lines.Count - 1 ) {
            $insert
        }
    } else { 
        $lines[$i]
    }
}

<强>输出

INSERT INTO DBname (id1, id2, id3, long, lat, [name]) VALUES 
(1, 1, 1, 42.48333330, 1.46666670, N'Aixàs'), 
(2, 1, 1, 42.46666670, 1.50000000, N'Aixirivali'), 
(3, 1, 1, 42.46666670, 1.50000000, N'Aixirivall'), 
(4, 1, 1, 42.46666670, 1.50000000, N'Aixirvall')
INSERT INTO DBname (id1, id2, id3, long, lat, [name]) VALUES 
(5, 1, 1, 42.46666670, 1.48333330, N'Aixovall'), 
(6, 2, 1, 42.50000000, 1.51666670, N'Andorra'), 
(7, 2, 1, 42.50000000, 1.51666670, N'Andorra la Vella'), 
(8, 2, 1, 42.50000000, 1.51666670, N'Andorra-Vieille')
INSERT INTO DBname (id1, id2, id3, long, lat, [name]) VALUES 
(9, 2, 1, 42.50000000, 1.51666670, N'Andorre'), 
(10, 2, 1, 42.50000000, 1.51666670, N'Andorre-la-Vieille')

答案 2 :(得分:0)

我会这样做:

$File = (Get-Content -Path $FilePath) -as [System.Collections.ArrayList];
$Offset = 5;
$InsertStatement = 'INSERT INTO DBname (id1, id2, id3, long, lat, [name]) VALUES';

$File.Count..0 | Where-Object {
        ($_ % $Offset) -eq 0
    } | ForEach-Object {
        if ($_ -gt 0) {
            $File[$_ - 1] = $File[$_ - 1].Trim().TrimEnd(',');
        }
        $File.Insert($_,$InsertStatement);
    }

while (($File[$File.Count - 1] -eq $InsertStatement) -or [System.String]::IsNullOrWhiteSpace($File[$File.Count - 1])) {
    $File.Remove($File.Count - 1);
}

File[$File.Count - 1] = $File[$File.Count - 1].Trim().TrimEnd(',');

Set-Content -Path $OutputFile -Value $File;

以下是对代码的解释:

$File = (Get-Content -Path $FilePath) -as [System.Collections.ArrayList];

将文件的内容读入ArrayList而不是普通的Array,因为它有一个稍后会有用的Insert方法。

$Offset = 5;
$InsertStatement = 'INSERT INTO DBname (id1, id2, id3, long, lat, [name]) VALUES';

这里我们定义行数和INSERT语句。

$File.Count..0

返回一个数组,以项目数的计数开始,以0结尾。我们将它用于ArrayList的索引。重要的是要注意我们首先从高数字开始然后降序,因为我们将在数组中插入项目,这将改变后续项目的索引。

               | Where-Object {
        ($_ % $Offset) -eq 0
    }

这里我们筛选出不是偏移倍数的任何数字。 %是模运算符,并返回除以两个数字的整数余数,因此9 % 54,但10 % 50。这是查找我们需要的索引的简便方法。

     | ForEach-Object {
        if ($_ -ne 0) {
            $File[$_ - 1] = $File[$_ - 1].Trim().TrimEnd(',');
        }
        $File.Insert($_,$InsertStatement);
    }

对于通过管道传递的每个索引,我们有两个操作要做。首先,我们采用我们需要的项来删除逗号,修剪任何尾随空格,然后从末尾修剪逗号。如果当前索引为零,我们跳过这个。接下来,我们在刚删除逗号的项之后在索引中插入INSERT语句。请注意,此处的索引为$_ - 1$_,因为ArrayLists从零开始编制索引。我们也不必担心插入后索引会移动,因为我们从文件末尾开始。

while (($File[$File.Count - 1] -eq $InsertStatement) -or [System.String]::IsNullOrWhiteSpace($File[$File.Count - 1])) {
    $File.Remove($File.Count - 1);
}

删除文件末尾的任何行,即INSERT语句或仅为空格。

File[$File.Count - 1] = $File[$File.Count - 1].Trim().TrimEnd(',');

从文件的最后一行删除最后一个逗号。

Set-Content -Path $OutputFile -Value $File;

将内容保存到$OutputFile

答案 3 :(得分:0)

如果输入文件很大,那么所有这些解决方案都不会很好,因为它们会将整个文件读入内存。这将是一个更好的解决方案:

$input = 'C:\temp\test.txt'
$output = 'C:\temp\output.txt'
$blocksize = 900

Get-Content $input | foreach {
    if (($_.ReadCount - 1) % $blocksize -eq 0) {
        # the first line of a block
        "INSERT INTO DBname (id1, id2, id3, long, lat, [name]) VALUES"
        $_
    } elseif ($_.ReadCount % $blocksize -eq 0) {
        # the last line of a block
        $_.Replace("),", ")")
        ""
    } else {
        # all other lines
        $_
    }
} | Out-File $output -Encoding UTF8