【问题标题】:Powershell to count columns in a filePowershell 对文件中的列进行计数
【发布时间】:2014-04-16 20:00:18
【问题描述】:

在导入 SQL 之前,我需要测试文件的完整性。 文件的每一行应具有完全相同的列数。

这些是“|”分隔文件。 我还需要忽略第一行,因为它是垃圾。

如果每一行没有相同的列数,那么我需要写一个错误信息。

我尝试过使用类似以下的方法,但没有成功:

$colCnt = "c:\datafeeds\filetoimport.txt"
$file = (Get-Content $colCnt -Delimiter "|") 
$file = $file[1..($file.count - 1)]
Foreach($row in $file){
    $row.Count
}

计算行数很容易。列不是。 有什么建议吗?

【问题讨论】:

  • 行分隔或列用“|”分隔? ss64.com/ps/get-content.html 在这种情况下,相信代码说明该行由“|”分隔(而不是换行符)

标签: powershell powershell-3.0


【解决方案1】:

是的,跳过第一行读取文件。对于每一行,在管道上拆分它,并计算结果。如果和前面的不一样,就抛出错误并停止。

$colCnt = "c:\datafeeds\filetoimport.txt"
[int]$LastSplitCount = $Null
Get-Content $colCnt | ?{$_} | Select -Skip 1 | %{if($LastSplitCount -and !($_.split("|").Count -eq $LastSplitCount)){"Process stopped at line number $($_.psobject.Properties.value[5]) for column count mis-match.";break}elseif(!$LastSplitCount){$LastSplitCount = $_.split("|").Count}}

应该这样做,如果它发现错误的列数,它将停止并输出如下内容:

Process stopped at line number 5 for column count mis-match.

编辑:添加了 Where 捕捉以跳过空白行 (?{$_})
编辑 2: 好的,如果您知道列数应该是多少那么这就更容易了。

Get-Content $colCnt | ?{$_} | Select -Skip 1 | %{if(!($_.split("|").Count -eq 210)){"Process stopped at line number $($_.psobject.Properties.value[5]), incorrect column count of: $($_.split("|").Count).";break}}

如果您希望它返回所有不包含 210 列的行,只需删除 ;break 并让它运行。

【讨论】:

  • 这非常有效。唯一我没有想到的是这些文件的底部通常有一两行空。有没有办法忽略空行和页脚?
  • 更新了我的答案以处理空行。老实说,mjolinor 的答案比我的更性感,但我的答案简单而实用。他的优点是可以捕捉所有不匹配的线条。我想我的可以修改为这样做,但它会变得丑陋。两者都有将整个事情建立在第一排的缺陷。如果它是错误的,那么对于任何一个答案,这一切都会变成锅底。如果你需要一些可以解释的东西,我可以做到,但它会需要更多的代码并且可能会更慢。
  • 您正确使用第一行。没想到。我知道列数应该是多少(210),所以会努力调整脚本以使用该变量
  • 更新了准确的列数。这确实使事情变得容易得多,您应该将其包含在原始帖子中=)
  • 这篇文章很棒。我有个问题。有没有办法从 DOUBLE QUOTE 值中删除逗号,在尝试确定我是否超过列数时计算逗号?我不确定是否有人会看到这篇文章,但我们将不胜感激。谢谢。
【解决方案2】:

更通用的方法,包括 RegEx 过滤器:

$path = "path\to\folder"
$regex = "regex"
$expValue = 450

$files= Get-ChildItem $path | Where-Object {$_.Name -match $regex}
Foreach( $f in $files) {
    $filename = $f.Name
    echo $filename
    $a = Get-Content $f.FullName;
    $i = 1;
    $e = 0;
    echo "Starting...";
    foreach($line in $a)
    {
        if ($line.length -ne $expValue){
            echo $filename
            $a | Measure-Object -Line
            echo "Long:"
            echo $line.Length;
            echo "Line Nº: "
            echo $i;
            $e = $e + 1;       
        }
        $i = $i+1;
    }
    echo "Finished";
    if ($e -ne 0){
        echo $e "errors found";
    }else{
        echo "No errors"
        echo ""
    }
}
echo "All files examined"

【讨论】:

    【解决方案3】:

    另一种可能性:

    $colCnt = "c:\datafeeds\filetoimport.txt"
    
    $DataLine = (Get-Content $colCnt -TotalCount 2)[1]
    $DelimCount = ([char[]]$DataLine -eq '|').count
    $MatchString = '.*' + ('|.*' * $DelimCount )
    
    $test = Select-String -Path $colCnt -Pattern $MatchString -NotMatch |
      where { $_.linenumber -ne 1 }
    

    这将在第二行中找到分隔符的数量,并构建一个可以与Select-String 一起使用的正则表达式模式。

    -NotMatch 开关将使它返回与该模式不匹配的任何行作为 MatchInfo 对象,这些对象将具有问题行的文件名、行号和内容。

    编辑:由于第一行是“垃圾”,因此您可能不在乎它是否不匹配,因此我在结果中添加了一个过滤器以将其删除。

    【讨论】:

      猜你喜欢
      • 2020-03-31
      • 1970-01-01
      • 2019-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-16
      • 1970-01-01
      相关资源
      最近更新 更多