【问题标题】:How to insert two lines for every data frame using awk?如何使用 awk 为每个数据帧插入两行?
【发布时间】:2014-12-06 20:58:34
【问题描述】:

我有如下重复数据

....
 4 4 4 66 79 169 150 0  40928  40938  40923  40921  40789  40000  40498
 5 4 3 16 22 247 0  40168  40911  40944  40205  40000  40562
 6 4 4 17 154 93 309 0  40930  40919  40903  40917  40852  40000  40419
 7 3 2 233 311 0  40936  40932  40874  40000  40807
....

这个数据是由115个数据块组成的,每个数据块有4000行这样的格式。 在这里,我希望在每个数据块的开头添加两个新行(每个数据块的行数= 4000和空行),这样看起来

4000

 1 4 4 244 263 704 952 0  40936  40930  40934  40921  40820  40000  40570
 2 4 4 215 172 305 33 0  40945  40942  40937  40580  40687  40000  40410
 3 4 4 344 279 377 1945 0  40933  40915  40907  40921  40839  40000  40437
 4 4 4 66 79 169 150 0  40928  40938  40923  40921  40789  40000  40498
...
 3999 2 2 4079 4081 0  40873  40873  40746  40000  40634
 4000 1 1 4080 0  40873  40923  40000  40345
4000

 1 4 4 244 263 704 952 0  40936  40930  40934  40921  40820  40000  40570
 2 4 4 215 172 305 33 0  40945  40942  40937  40580  40687  40000  40410
 3 4 4 344 279 377 1945 0  40933  40915  40907  40921  40839  40000  40437
 4 4 4 66 79 169 150 0  40928  40938  40923  40921  40789  40000  40498
... 

我可以使用 awk 或任何其他 unix 命令来执行此操作吗?

【问题讨论】:

    标签: awk insert lines


    【解决方案1】:

    我的解决方案更通用,因为只要您重新启动第一个字段计数器以表示新块的开始,块的长度就可以不相等

    % cat mark_blocks
    $1<count { print count; print "";
               for(i=1;i<=count;i++) print l[i]; }
    # executed for each line
             { l[$1] = $0; count=$1}
    END      { print count; print "";
               for(i=1;i<=count;i++) print l[i]; }
    % awk -f mark_blocks your_data > marked_data
    % 
    

    工作很简单,awk 在内存中累积行,当到达新的块或 EOF 时打印标题行和累积的数据。

    (适度的)技巧是必须在我们为每一行执行通常的操作之前执行输出操作。

    【讨论】:

      【解决方案2】:

      使用awk 的简单单行就可以达到目的。

      awk 'NR%4000==1{print "4000\n"} {print$0}' file

      它的作用。

      print $0 打印每一行。 NR%4000==1 选择4000th 行。当它发生时,它会打印一个4000 和一个换行符\n,即两个新行。

      NR记录数,即目前有效读取的行数。

      简单的测试。

      在第 5 行插入 4000

      awk 'NR%5==1{print "4000\n"} {print$0}'

      输出:

      4000
      
      1
      2
      3
      4
      5
      4000
      
      6
      7
      8
      9
      10
      4000
      
      11
      12
      13
      14
      15
      4000
      
      16
      17
      18
      19
      20
      4000
      

      【讨论】:

      • 您能否将输出的前三行与需求示例的前三行进行比较?您的一个衬里应该写为NR%4000==1{print "4000\n} 1,以便在打印#1、#4001、#8001 等行之前打印标题。
      • 它是NR%4000==1{print "4000\n"} 1(有一个开头和一个关闭双引号......)。
      • @gboffi 你找到我了。已更正。谢谢你:)
      • 我看到了两个小缺陷...(1)您的第一行代码中的 file 参数需要一个空格来与 awk 程序分开,并且(2)您忘记更新您的算法的描述,仍然是指您之前的实现的描述。
      【解决方案3】:

      您可以在 bash 中完成所有操作:

      cat $FILE | ( let countmax=4000; let count=countmax; while read lin ; do if [ $count == $countmax ]; then let count=0; echo -e "$countmax\n" ; fi ; echo $lin ; let count=count+1 ; done )
      

      这里我们假设您正在从 $FILE 读取这些数据。然后我们所做的就是从文件中读取并将其通过管道传输到我们的小 bash 脚本中。

      bash 脚本逐行读取(使用while read lin),并为每一行递增计数器count。启动时或当计数器 count 达到值 countmax (设置为 4000) 时,它会打印出您要求的 2 行。

      【讨论】:

      • 谢谢,但这给了我两个空行,而不是 1 个空行。所以,这段代码产生了 3 行额外的结果。
      猜你喜欢
      • 2022-01-13
      • 1970-01-01
      • 2021-06-22
      • 1970-01-01
      • 1970-01-01
      • 2019-12-30
      • 1970-01-01
      • 2022-01-11
      • 2021-05-08
      相关资源
      最近更新 更多