如何用PowerShell移除CSV文件中表格数据以外的行?
解决PowerShell清理CSV非表格行并导入SQL的问题
你的思路核心是对的,但CSV是纯文本文件,没有Excel的UsedRange属性,我们可以换个方式:先正确解析每行的列数,找到表格的标准列数,再筛选出列数匹配的行,自动去掉前面的非表格内容。下面是直接能用的脚本,带详细注释,你替换成自己的路径和SQL信息就行。
步骤1:清理CSV文件(自动删除前置非表格行)
# -------------------------- # 替换成你的文件路径 # -------------------------- $原始CSV路径 = "C:\你的文件夹\输入文件.csv" $清理后CSV路径 = "C:\你的文件夹\清理后的文件.csv" $CSV分隔符 = "," # 如果是制表符分隔的CSV,改成 "`t" # 加载.NET的CSV解析工具(避免直接分割逗号出错,比如带引号的字段里的逗号) Add-Type -AssemblyName Microsoft.VisualBasic # 第一步:遍历所有行,找到表格的最大列数 $最大列数 = 0 $临时文件路径 = [System.IO.Path]::GetTempFileName() Get-Content -Path $原始CSV路径 -Raw | Out-File -Path $临时文件路径 -Encoding utf8 $解析器 = New-Object Microsoft.VisualBasic.FileIO.TextFieldParser($临时文件路径) $解析器.TextFieldType = [Microsoft.VisualBasic.FileIO.FieldType]::Delimited $解析器.SetDelimiters($CSV分隔符) $解析器.HasFieldsEnclosedInQuotes = $true # 处理带引号的字段(比如"张三,李四"这种) while (!$解析器.EndOfData) { try { $当前行列数 = $解析器.ReadFields().Count if ($当前行列数 -gt $最大列数) { $最大列数 = $当前行列数 } } catch { continue } # 跳过解析失败的行(比如空行) } $解析器.Close() Remove-Item $临时文件路径 -Force # 第二步:重新读取文件,只保留列数等于最大列数的行 $解析器 = New-Object Microsoft.VisualBasic.FileIO.TextFieldParser($原始CSV路径) $解析器.TextFieldType = [Microsoft.VisualBasic.FileIO.FieldType]::Delimited $解析器.SetDelimiters($CSV分隔符) $解析器.HasFieldsEnclosedInQuotes = $true $清理后的行 = @() while (!$解析器.EndOfData) { try { $当前行字段 = $解析器.ReadFields() if ($当前行字段.Count -eq $最大列数) { # 将字段重新拼接成符合CSV规范的行(处理带引号的内容) $处理后的行 = $当前行字段 | ForEach-Object { if ($_ -match "[,$CSV分隔符`"]") { '"' + $_.Replace('"', '""') + '"' } else { $_ } } -join $CSV分隔符 $清理后的行 += $处理后的行 } } catch { continue } } $解析器.Close() # 将清理后的内容写入新CSV $清理后的行 | Out-File -Path $清理后CSV路径 -Encoding utf8 -NoNewline
步骤2:导入清理后的CSV到SQL临时表
# -------------------------- # 替换成你的SQL服务器信息 # -------------------------- $SQL服务器 = "你的SQL服务器名\实例名" $数据库名 = "你的数据库名" $临时表名 = "你的Staging表名" # 先安装SqlServer模块(第一次运行需要执行,之后可以注释掉) # Install-Module SqlServer -Scope CurrentUser # Set-ExecutionPolicy RemoteSigned -Scope CurrentUser # 允许运行PowerShell脚本 Import-Module SqlServer # 导入CSV到SQL表(如果CSV表头和SQL表列名一致,直接用下面的命令) Import-SqlTableData -ServerInstance $SQL服务器 -Database $数据库名 ` -TableName $临时表名 -InputFile $清理后CSV路径 # 如果CSV表头和SQL列名不一致,添加列映射: # $列映射 = @{ "CSV列名1" = "SQL列名1"; "CSV列名2" = "SQL列名2" } # Import-SqlTableData -ServerInstance $SQL服务器 -Database $数据库名 ` # -TableName $临时表名 -InputFile $清理后CSV路径 -ColumnMap $列映射
注意事项
- 如果你的CSV是GBK编码(比如中文乱码),读取的时候把
Get-Content改成Get-Content -Path $原始CSV路径 -Raw -Encoding Default - 要是运行脚本提示权限问题,以管理员身份打开PowerShell再执行
- 如果
最大列数为0,说明原始CSV文件有问题,需要检查文件内容
内容的提问来源于stack exchange,提问作者tom pratt
相关产品推荐
相关产品推荐

