【问题标题】:Adding a column or row to a csv file (matlab or cmd)将列或行添加到 csv 文件(matlab 或 cmd)
【发布时间】:2015-06-23 14:01:38
【问题描述】:

我相信这是一个非常常见的问题,但我找不到足够准确的答案。我需要使用 MATLAB 或使用足够简单的命令行提示符得到答案。 我在一个目录中有(许多).csv 文件,它们都相似。假设文件看起来像,

1,2
3,4

我现在希望它们看起来像

,c1,c2
t1,1,2
t2,3,4

我不能 100% 确定如何在 StackExchange 上正确设置条目的格式。第一行和第二行之间没有空行。我正在做的是 - 我在所有文件中添加一列“t1 t2 ...”和行“c1 c2 ...”。文件中的第一个单元格是空白的。我需要对我目录中的所有文件执行此操作。当然,t1 t2 值和 c1 c2 值应该针对整个文件大小运行。

我该如何做到这一点?

【问题讨论】:

  • 你是不是想搞个阴谋?使用列和行标题?可以重新格式化您的示例输入和所需的输出吗?
  • 不,不是情节。我需要这种特定格式,因为另一个软件(GAMS)单独使用它。我可以在 Excel 上重新格式化,但文件夹中有数千个文件。
  • @EdMorton 你是完全正确的。我不知道如何格式化我的问题。

标签: matlab csv awk sed append


【解决方案1】:

这是另一个 awk 脚本:

#!/usr/bin/awk -f

BEGIN { FS=OFS="," }
{
    if( FNR==1 ) {
        close(fn); fn=FILENAME ".new"; printf OFS > fn

        for(i=1; i<=NF; i++) {
            printf "c%d%s", i, (i!=NF) ? OFS:"\n" > fn
        }
    }
    print "t"FNR OFS $0 > fn
}

执行以下操作:

  • BEGIN { FS=OFS="," } - sets the field separators to,`
  • FNR==1 - 在每个输入文件的第一行,close(fn) 如果它打开,设置fn 等于“你的文件名.new”,然后打印一个前导,FNR 是当前文件中的行号。
  • 还根据第一个数据行中的字段数创建 c# 标头并将其打印到 fn

然后,将所有行视为有效数据行(无 cmets):

  • 在每个数据行前添加t# OFS,然后将其打印到fn

我将 awk 脚本放入了一个文件 script.awk,然后是 chmod +x script.awk

给定以下两个输入数据文件(data1data2)在同一目录中:

cat data1 data2
1,2 
3,4 
1,2,3
4,5,6
7,8,9

script.awk data* 这样运行脚本会得到以下两个.new 数据文件:

cat data1.new data2.new
,c1,c2
t1,1,2 
t2,3,4 
,c1,c2,c3
t1,1,2,3
t2,4,5,6
t3,7,8,9

只要文件名彼此相似并且与脚本名称不匹配,就应该很容易将它们全部传递给脚本。随着数字长度的增加,我没有任何对齐列的操作,仅足以为c# 行提供一个前导空间。

【讨论】:

  • 感谢您的回答,以及漂亮的格式。如您所见,我仍在学习格式化我的问题。当我执行 script.awk data* 时,我收到错误“script.awk: command not found”。我确实将 awk 脚本放入 script.awk 文件和 chmod 命令中。我做错了什么?
  • 对不起。由于我经常使用csh,所以我总是忘记在问题脚本中添加./。如果您使用 bash,请尝试 ./script.awk data*
  • 更有意义。所以我应该做 chmod +x script.awk 后跟 ./script.awk data* ,对吗?第二个产生错误“(没有这样的文件或目录)”。我可以“ls”并看到 script.awk 确实是文件夹中的可执行文件,data1 和 data2 也是如此。
  • awk -f script.awk data* 能为您做什么?
  • 酷。因此,现在生成了 .new 文件,但是在其中找不到我需要的格式(以及您在答案中显示的格式)。相反,data1.new 如下所示:第一行:“1 2”第二行:空白第三行:“space c1 c2”第四行:“t1 3 4”c1 c2 t1 3 4
【解决方案2】:

你应该展示一些你已经累了的代码,如果它不起作用,你可以问堆栈溢出的人,这里的大多数人甚至不会在没有代码的情况下帮助你。以下是要做什么的大纲,您可以在自己喜欢的编程语言/环境中实现它

  1. 创建一个新的输出文件
  2. 打开您现有的 csv 文件
  3. 将新行添加到 输出 文件 (c1 c2 c3..) 的顶部
  4. csv中的每一行

    现在我们正在尝试在输出文件中创建每一行

    一个。使用空格(或其他分隔符)分割行

    b.将 t1 写入 输出 并插入分隔符

    c。从你的分裂中写出第一个和第二个“令牌”

    d。将 t2 写入 输出 并插入分隔符

    e。将剩余的列写入该行

    f。在输出文件中插入换行符

  5. 关闭 csv输出 文件

可选的“覆盖”原始 csv

  1. 删除原始csv
  2. 输出 文件重命名为旧的 csv 文件名

【讨论】:

    【解决方案3】:
    awk '{
          FS=" "
          if (NR == 1) {
             printf ("%s", FS)
             for (col=1;col < NF;col++) printf( "c%d%s", col, FS)
             printf( "c%d\n", NF)
             }
         if ( $0 !~ /^[[:space:]]*$/ ) {
             printf ( "t%d%s%s\n", NR, FS, $0)
             }
         }' YourFile
    
    • 在这里假设(对于 csv 来说很奇怪)空格是分隔符,对于任何更传统的分隔符,只需使用您的分隔符值调整 FS=" "
    • 在第一行添加标题列
    • 添加tX 行首
    • 以第一行作为标题列数的参考

    添加 find ... 或批处理循环以在文件夹中的每个 csv 中更改它

    【讨论】:

      【解决方案4】:

      -i inplace 使用 GNU awk 4.*:

      $ cat tst.awk
      BEGIN { FS=OFS="," }
      FNR==1 {
          for (i=1;i<=NF;i++)
              printf "%sc%d%s",(i>1?"":OFS),i,(i<NF?OFS:ORS)
      }
      { print "t" FNR, $0 }
      
      $ cat file
      1,2
      3,4
      
      $ awk -i inplace -f tst.awk file
      
      $ cat file
      ,c1,c2
      t1,1,2
      t2,3,4
      

      只需将file 更改为*,它就会更新您目录中的每个文件。

      【讨论】:

        猜你喜欢
        • 2013-08-03
        • 2022-01-08
        • 1970-01-01
        • 1970-01-01
        • 2022-01-23
        • 2018-01-01
        • 2013-06-27
        • 2015-08-12
        • 2015-11-29
        相关资源
        最近更新 更多