使用PowerShell编辑500多个类似的文本文件

时间:2015-04-07 19:48:34

标签: powershell batch-file

我有超过500个文本文件,其中包含纬度,经度和值的列。每个文件都根据年份和月份命名(因此2015年2月是201502_stag.txt,1983年3月是198303_stag.txt等),但此信息不包含在文件本身中。数据看起来像这样:

-140.00   55.00   2
-140.00   54.75   7 
-140.00   54.50   3 

我想做三件我不知道该怎么做的事情,因为我对使用PowerShell这么新:

1。)将每个文件的标题放入文件中的重复列中(以便年份和月份不会混淆)

2。)删除文件中所有条目,其中lat和long在我感兴趣的区域之外(以最小值和最大值为单位为lat,每个为长),

3.。)将所有这些文件附加在一起

我一直在使用一个教程来试图解决这个问题,而我现在想出了自己的#3。我正在摸不着其余的事情,真的很想学习!

3 个答案:

答案 0 :(得分:1)

他也可以做​​到这一点。为了尝试采用不同的方法,我将输出更改为CSV格式。如果你不需要,那就很容易改变它。

$files = Get-ChildItem "C:\path\*stag.txt"
$files | ForEach-Object{
    $filedate = ($_.BaseName).Split("_")[0]
    Get-Content $_ | ForEach-Object{
        $line = $_ -split "\s+"
        New-Object -TypeName PsCustomObject  -Property @{
            Date = $filedate
            Lat = $line[0]
            Long = $line[1]
            Index = $line[2]
        }
    }
} | Where-Object{[double]$_.Lat -lt -150 -and [double]$_.Long -lt 54.75} | 
    Select-Object Date,Lat,Long,Index | 
    Export-CSV C:\temp\outputfile.csv -Delimiter "`t" -NoTypeInformation

这将使一个目录中的所有文件以" stag.txt"结尾。获取所有内容并将其转换为具有Date,Lat,Long和Index属性的PowerShell对象。我不知道最后一个值是什么,所以我称之为索引。日期来自" _"之前的文件名部分。

然后,由于我们将它作为自定义对象,我们可以使用Where-Object和我们之前定义的属性。我们将值转换为[double]以供我们使用数字比较作为字母数字。将其导入Select-Object以获取正确的顺序并导出到制表符分隔的CSV。

我假设你有PowerShell 1或2.如果你有至少3个,这将更简洁,但我根据你的经验假设。

为了测试,我制作了2个包含以下内容的文件

#198303_stag.txt
-140.00   55.00   2
-150.00   54.75   7 
-160.00   54.50   3 
#201502_stag.txt
-140.00   58.00   2
-140.00   54.75   7 
-140.00   59.50   3 

上述代码的输出是

"Date"  "Lat"   "Long"  "Index"
"198303"    "-160.00"   "54.50" "3"

输出批评

如果你不喜欢这里所做的事情,那么进行一些改变并不是一件容易的事。只是让我知道你在找什么。

答案 1 :(得分:0)

哦,你可以用一个班轮做到这一点。

gci *stag.txt | %{ $f = $_; gc $f | %{ $l=$_ -split '\s+'; if ([float]$l[0] -eq -140.00 -and [float]$l[1] -ge 50) { $_ + '  ' + $f.Name | ac 'merged.txt' } } }

让我们分解。

<#
    gci is an alias for Get-ChildItem.
    % is an alias for For-Each.
    So, for each file in the current dir matching *stag.txt...
#>
gci *stag.txt | %{

    # Set $f to the current file object.
    $f = $_;

    # Get-Content of the file object.  For each line...
    gc $f | %{

        # $l = the line split on one or more spaces.
        $l = $_ -split '\s+';

        <#
            If...
                * the first word equals -140, and
                * the second word is greater than or equal to 50
            Then...
        #>
        if ([float]$l[0] -eq -140.00 -and [float]$l[1] -ge 50) {

            <#
                Append-Content to merged.txt
                * The unmodified line
                * Literal two spaces
                * The name of the file
            #>
            $_ + '  ' + $f.Name | ac 'merged.txt'
        }
    }
}

虽然此解决方案实际上并未删除原始文件中的任何行,但不相关的行将从merged.txt中排除。

答案 2 :(得分:0)

如果您使用Powershell v3或更高版本($ PSVersiontable),请尝试以下操作:

    # specify path to files
    $path = "path\to\files"

    # thresholds. casting to [double] to use arithmetic operations on them
    $latmin = [double]-150
    $latmax = [double]-120
    $longmin = [double]54.75
    $longmax = [double]60

    # array for output. cache all results here before export to file, this will minimize IO operations and save some time
    $out = @()

    # read file by file
    foreach ($file in Get-ChildItem -Path $path -Filter "*_stag.txt") 
    {
        # display some progress information
        echo "Proceeding file $file"
        $filename = $file.BaseName.Replace('_stag','') # or just $file.BaseName
        # read contents
        $contents = (Get-Content $file.FullName)
        # proceed every line, splitting by whitespace (one or more)
        # if field delimiter is tab character, replace splitter with '\t+'
        # for each line we construct an object and add it to output array
        $contents | foreach { $tokens = $_ -split '\s+'; $out += [pscustomobject]@{Date = $filename; Lat = [double]$tokens[0]; Long = [double]$tokens[1]; Num = [int]$tokens[2]}  }
    }
    $out | ft
    # exclude unnecessary entries and export to file
    $out | where { ($_.Lat -ge $latmin) -and ($_.Lat -le $latmax) -and ($_.Long -ge $longmin) -and ($_.Long -le $longmax) } | Out-File -Encoding utf8 "$path\out.txt"

只需指定文件和条件的路径即可。

编辑:

转换为[double]而不是[int]。感谢Matt。