如何在PowerShell中实现与Linux脚本等效的文本文件指定经纬度提取及合并输出
优化PowerShell脚本:提取TXT文件中的起始经纬度并生成汇总文件
需求背景
我需要处理当前目录下所有.txt文件,完成以下操作:
- 搜索包含
Start l的行(会匹配Start latitude和Start longitude两行) - 提取这两行里的数值部分
- 将文件名(不含后缀)、纬度值、经度值合并为一行,格式示例:
CC2019012_20220601_125156,39.0285453,-74.4891558 - 最终把所有结果统一写入
locations.sam文件
示例参考
执行命令:
select-string -path .\CC2019012_20220601_125156.txt -Pattern 'Start l'
返回结果:
CC2019012_20220601_125156.txt:10:% Start latitude,39.0285453
CC2019012_20220601_125156.txt:11:% Start longitude,-74.4891558
期望得到的输出行:
CC2019012_20220601_125156,39.0285453,-74.4891558
现有PowerShell脚本
我自己写了一段基础实现,但想寻求更高效、更严谨的优化方案:
foreach ($file in gci *.txt) { $base = (Get-Item "$file" ).Basename $var = select-string -path $file -Pattern 'Start l' | %{$_ -replace "..*,",""} $join = $var -join "," echo "$base,$join" | out-file -Append .\locations.sam }
优化后的脚本方案
这里提供几个优化方向,兼顾性能、可读性和鲁棒性:
1. 提升性能:减少重复文件IO操作
原脚本每次循环都用Out-File -Append频繁读写文件,会拖慢处理速度。可以先把所有结果收集到内存中,最后一次性写入:
$results = foreach ($file in Get-ChildItem -Filter *.txt) { $baseName = $file.BaseName # 匹配目标行并提取数值,确保纬度始终排在经度前面 $coords = Select-String -Path $file.FullName -Pattern 'Start (latitude|longitude)' | Sort-Object { $_.Line -match 'latitude' } | # 强制纬度优先 ForEach-Object { $_.Line -replace '^.*?,(.*)$', '$1' } # 仅当找到完整的经纬度两行时才输出 if ($coords.Count -eq 2) { "$baseName,$($coords -join ',')" } } # 一次性写入文件,覆盖原有内容(若需追加可改用 -Append) $results | Out-File -Path .\locations.sam -Encoding utf8
2. 更精准的匹配与提取逻辑
原脚本的"..*,"替换规则不够严谨,改用正则表达式'^.*?,(.*)$'可以精准定位逗号后的数值部分。同时增加排序步骤,避免因文件中行顺序不同导致经纬度颠倒。
3. 可选:添加错误提示
如果部分文件可能缺失目标行,可以添加警告提示,方便排查问题:
$results = foreach ($file in Get-ChildItem -Filter *.txt) { $baseName = $file.BaseName $coords = Select-String -Path $file.FullName -Pattern 'Start (latitude|longitude)' | Sort-Object { $_.Line -match 'latitude' } | ForEach-Object { $_.Line -replace '^.*?,(.*)$', '$1' } if ($coords.Count -eq 2) { "$baseName,$($coords -join ',')" } else { Write-Warning "文件 $($file.Name) 未找到完整的起始经纬度行" } } $results | Out-File -Path .\locations.sam -Encoding utf8
参考Linux实现
对应的Linux bash脚本实现供对比:
for file in *.txt do lat=$(grep -i "start l" $file | dos2unix | sed -e 's/^..*,//' | sed -e 'N;s/\n/,/') echo "$file,$lat" done >| locations.sam
内容的提问来源于stack exchange,提问作者Sam Alleman
相关产品推荐
相关产品推荐

