使用批处理文件编辑.csv文件

时间:2016-05-25 21:59:25

标签: csv batch-file

这是我在这里的第一个问题。我是一名气象学家并且有一些编码经验,尽管它远非专业教学。基本上我所拥有的是来自气象站的.csv文件,它给我的数据太详细了。 (65.66度和类似的值)我想要做的是通过脚本文件自动化一种方式,该文件将访问.csv文件并删除过于详细的值。 (将温度从65.66提高到66(对于任何高于.5以及向下用于下方),或者使用相同的舍入规则进行压力(29.8889)并使其成为(29.89)。这是否可以实现?如果是这样,我应该怎么做呢。再次请记住,我对批处理文件的编码技巧并不是最强的。

非常感谢任何帮助。

谢谢,

2 个答案:

答案 0 :(得分:2)

我同意上述评论。批量数学仅限于整数,并且不适合您想要的操作。

我会使用PowerShell。除了轻松处理浮点数学之外,它还具有用于对CSV数据(以及XML和其他类型的结构化数据)进行客观化的内置方法。获取weather.csv中包含的以下假设CSV数据:

date,time,temp,pressure,wx
20160525,12:30,65.66,30.1288,GHCND:US1TNWS0001
20160525,13:00,67.42,30.3942,GHCND:US1TNWS0001
20160525,13:30,68.92,31.0187,GHCND:US1TNWS0001
20160525,14:00,70.23,30.4523,GHCND:US1TNWS0001
20160525,14:30,70.85,29.8889,GHCND:US1TNWS0001
20160525,15:00,69.87,28.7384,GHCND:US1TNWS0001

您要做的第一件事是将数据作为对象导入(使用import-csv),然后根据需要舍入数字 - temp舍入为整数,压力舍入为2的十进制精度地方。四舍五入很容易。只需将数据重新整理为整数。它会自动舍入。如果您调用.NET [math]::round()方法,那么舍入压力列也非常简单。

# grab CSV data as a hierarchical object
$csv = import-csv weather.csv

# for each row of the CSV data...
$csv | foreach-object {

    # recast the "temp" property as an integer
    $_.temp = [int]$_.temp

    # round the "pressure" property to a precision of 2 decimal places
    $_.pressure = [math]::round($_.pressure, 2)
}

现在假装您要显示“日期”= 20160525和“时间”= 14:30的温度,气压和气象站名称。

$row = $csv | where-object { ($_.date -eq 20160525) -and ($_.time -eq "14:30") }
$row | select-object pressure,temp,wx | format-table

假设“压力”开始时的值为29.8889,而“temp”的值为70.85,则输出为:

pressure temp wx
-------- ---- --
   29.89   71 GHCND:US1TNWS0001

如果CSV数据有多行具有相同的日期和时间值(可能来自不同气象站的测量值),那么该表将显示多行。

如果您想将其导出到新的csv文件,只需将format-table cmdlet替换为export-csv destination.csv

$row | select-object pressure,temp,wx | export-csv outfile.csv

作为衬衫上的口袋方便,对吗?

现在,假装您想要显示人类可读的电台名称而不是NOAA的名称。制作哈希表。

$stations = @{
    "GHCND:US1TNWS0001" = "GRAY 1.5 E TN US"
    "GHCND:US1TNWS0003" = "GRAY 1.9 SSE TN US"
    "GHCND:US1TNWS0016" = "GRAY 1.3 S TN US"
    "GHCND:US1TNWS0018" = "JOHNSON CITY 5.9 NW TN US"
}

现在您可以为“行”对象添加“station”属性。

$row = $row | select *,"station"
$row.station = $stations[$row.wx]

现在如果你这样做了:

$row | select-object pressure,temp,station | format-table

您的控制台显示:

pressure temp station
-------- ---- -------
   29.89   71 GRAY 1.5 E TN US

要获得额外的功劳,请说您要将此行数据导出为JSON(对于网页或其他内容)。这有点复杂,但并非不可能。

add-type -AssemblyName System.Web.Extensions
$JSON = new-object Web.Script.Serialization.JavaScriptSerializer

# convert $row from a PSCustomObject to a more generic hash table
$obj = @{}

# the % sign in the next line is shorthand for "foreach-object"
$row.psobject.properties | %{
    $obj[$_.Name] = $_.Value
}

# Now, stringify the row and display the result
$JSON.Serialize($obj)

该输出应与此类似:

{"station":"GRAY 1.5 E TN US","wx":"GHCND:US1TNWS0001","temp":71,"date":"201605
25","pressure":29.89,"time":"14:30"}

...您可以使用>将其重定向到.json文件,或将其传递到out-file cmdlet。

答案 1 :(得分:2)

到目前为止,DOS批处理脚本不是编辑文本文件的最佳位置。但是,这是可能的。我将在本文的底部包含示例,不完整的DOS批处理代码以证明这一点。我建议你专注于Excel(不需要编码)或Python。

  • Excel - 您根本不需要使用Excel进行编码。打开csv文件。我们假设您在B12单元格中有66.667。在单元格C12中使用圆函数输入公式(代码如下)。您还可以自学一些Visual Basic for Applications。但是,对于这个简单的任务,这是过度的。完成后,如果您保存为csv格式,您将丢失公式并且只有数据。考虑保存为xlsx或xlsm。
  • Visual Basic脚本 - 您可以在计算机上运行vbscript cscript.exe(或wscript.exe),它是Windows的一部分。但是,如果使用VB脚本,您也可以在Excel中使用VBA。它几乎完全相同。
  • Python是一个非常高级的语言库,内置库 使编辑csv文件非常容易。我推荐Anaconda (一个Python套件)来自continuum.io。但是,你可以找到通用的Python python.org也是。 Anaconda将预先包装许多
    有用的图书馆对于csv编辑,您可能希望使用 熊猫图书馆。您可以在YouTube上找到大量短视频。

<强> Excel中

Say you have 66.667 in cell B12.  Set the formula in C13 to...
  "=ROUND(B12,0)" to round to integer
  "=ROUND(B12,1)" to round to one decimal place
As you copy and past, Excel will attempt to intelligently update the formulas for you.

<强>的Python

import pandas as pd  
from StringIO import StringIO
import numpy as np
# load csv file to memory. Name your columns "using names=[]"
df = pd.read_csv(StringIO("C:/temp/weather.csv"), names=["city", "temperature", "date"]) 
df["temperature"].apply(np.round) #you just rounded the temperature column 
pd.to_csv('newfile.csv') # export to a new csv file
pd.to_xls('newfile.xls') # or export to an excel file instead

DOS批次 这个批处理脚本要困难得多。我不会写整个程序,因为它不是一个很好的解决方案。但是,我将在本文的底部给你一个DOS批处理代码的味道。与使用Python或Excel相比,它非常复杂。

这是DOS代码的粗略草图。因为我不推荐这种方法,所以我没有花时间调试这段代码。

setlocal ENABLEDELAYEDEXPANSION
:: prep our new file for output.  Let's write the header row.
echo col1, col2, col3 >newfile.csv
:: read the existing text file line by line
:: since it is csv, we will parse on comma
:: skip lines starting with semi-colon
FOR /F "eol=; tokens=2,3* delims=, " %%i in (input_file.txt) do (
    set col1=%%I, set col2=%%J, set col3=%%K
    :: truncate col2 to 1 decimal place
    for /f "tokens=2 delims==." %%A in ("col2") do (
        set integer=%%A
        set "decimal=%%B
        set decimal=%decimal:~0,1%
        :: or, you can use an if statement to round up or down
        :: Now, put the integer and decimal together again and 
        :: redefine the value for col2.
        set col2=%integer%.%decimal%
        :: write output to a new csv file
        :: > and >> can redirect output from console to text file
        :: >newfile.csv will overwrite file.csv. We don't want 
        :: that, since we are in a loop.
        :: >>newfile.csv will append to file.csv, perfect!
        echo col1, col2, col3 >>newfile.csv
    )
)
:: open csv file in default application
start myfile.csv