【问题标题】:Another split file in bash - based on difference between rows of column xbash 中的另一个拆分文件 - 基于 x 列的行之间的差异
【发布时间】:2013-09-14 17:33:38
【问题描述】:

你好 stackoverflow 用户!

通常我想调整我正在使用的脚本,只是为了让它对丢失的数据更加不敏感。 我的示例数据如下所示(带有标题的制表符分隔的 csv 文件):

ColA    ColB    ColC
6   0   0
3   5.16551 12.1099
1   10.2288 19.4769
6   20.0249 30.6543
3   30.0499 40.382
1   59.9363 53.2281
2   74.9415 57.1477
2   89.9462 61.3308
6   119.855 64.0319
4   0   0
8   5.06819 46.8086
6   10.0511 60.1357
9   20.0363 71.679
6   30.0228 82.1852
6   59.8738 98.4446
3   74.871  100.648
1   89.9973 102.111
6   119.866 104.148
3   0   0
1   5.07248 51.9168
2   9.92203 77.3546
2   19.9233 93.0228
6   29.9373 98.7797
6   59.8709 100.518
6   74.7751 100.056
3   89.9363 99.5933
1   119.872 100

我使用在别处找到的awk脚本,如下:

awk 'BEGIN { fn=0 }
NR==1 { next }
NR==2 { delim=$2 }
$2 == delim {
    f=sprintf("file_no%02d.txt",fn++);
    print "Creating " f
}

{ print $0 > f }'

这给了我想要的输出 - 省略第一行,找到第二列并设置分隔符 - 在这个例子中它将是 '0':

file_no00.txt
6   0   0
3   5.16551 12.1099
1   10.2288 19.4769
6   20.0249 30.6543
3   30.0499 40.382
1   59.9363 53.2281
2   74.9415 57.1477
2   89.9462 61.3308
6   119.855 64.0319

file_no01.txt
4   0   0
8   5.06819 46.8086
6   10.0511 60.1357
9   20.0363 71.679
6   30.0228 82.1852
6   59.8738 98.4446
3   74.871  100.648
1   89.9973 102.111
6   119.866 104.148

    file_no02.txt
3   0   0
1   5.07248 51.9168
2   9.92203 77.3546
2   19.9233 93.0228
6   29.9373 98.7797
6   59.8709 100.518
6   74.7751 100.056
3   89.9363 99.5933
1   119.872 100

为了使脚本更健壮(假设删除了带有 0 的行),如果该值低于 0 拆分文件,我需要根据行 'n+1' 和 'n' 的减去值拆分文件,所以基本上如果(value_row_n+1)-value_row_n < 0 然后拆分文件。当然,我还需要维护文件命名。首选方式是 bashawk 使用。有什么建议吗?提前致谢!

干杯!

【问题讨论】:

  • if (n+1)-n < 0 将始终返回 FALSE 你能试着解释一下你的问题吗?
  • @anubhava 感谢您的评论,big file(第一个示例)中第二列的语句 'if (n+1)-n
  • 这里令人困惑的是,这不是(n+1)-n == 1? n 和另一个 n 不同吗?
  • @konsolebox 这就是重点,我将编辑问题以使其更清晰

标签: bash csv awk split


【解决方案1】:

这是您可以使用的 awk 命令:

cat file
ColA    ColB    ColC
3       5.16551 12.1099
1       10.2288 19.4769
6       20.0249 30.6543
3       30.0499 40.382
1       59.9363 53.2281
2       74.9415 57.1477
2       89.9462 61.3308
6       119.855 64.0319
8       5.06819 46.8086
6       10.0511 60.1357
9       20.0363 71.679
6       30.0228 82.1852
6       59.8738 98.4446
3       74.871  100.648
1       89.9973 102.111
6       119.866 104.148
1       5.07248 51.9168
2       9.92203 77.3546
2       19.9233 93.0228
6       29.9373 98.7797
6       59.8709 100.518
6       74.7751 100.056
3       89.9363 99.5933
1       119.872 100
awk 'NR == 1 {
  next
}
!p || $2 < p {
   f = sprintf("file_no%02d.txt",fn++);
   print "Creating " f
}
{
   p = $2;
   print $0 > f
}' file

【讨论】:

    【解决方案2】:

    我建议对您当前的脚本进行一些小修改:

    awk 'BEGIN { fn=0; f=sprintf("file_no%02d.txt",fn++); print "Creating " f }
    NR==1 { next }
    NR==2 { delim=$2 }
    $2 - delim < 0 {
        f=sprintf("file_no%02d.txt",fn++);
        print "Creating " f
    }
    
    { print $0 > f; delim = $2 }' infile
    

    首先,在开始处理之前创建第一个文件名。

    其次,在最后一个条件下保存当前行的值与下一行的值进行比较。

    第三,不是与零的比较,而是在前一个值和当前值之间进行减法,以检查结果是否小于零。

    它产生:

    ==> file_no00.txt <==
    6   0   0
    3   5.16551 12.1099
    1   10.2288 19.4769
    6   20.0249 30.6543
    3   30.0499 40.382
    1   59.9363 53.2281
    2   74.9415 57.1477
    2   89.9462 61.3308
    6   119.855 64.0319
    
    ==> file_no01.txt <==
    4   0   0
    8   5.06819 46.8086
    6   10.0511 60.1357
    9   20.0363 71.679
    6   30.0228 82.1852
    6   59.8738 98.4446
    3   74.871  100.648
    1   89.9973 102.111
    6   119.866 104.148
    
    ==> file_no02.txt <==
    3   0   0
    1   5.07248 51.9168
    2   9.92203 77.3546
    2   19.9233 93.0228
    6   29.9373 98.7797
    6   59.8709 100.518
    6   74.7751 100.056
    3   89.9363 99.5933
    1   119.872 100
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-12
      • 1970-01-01
      • 1970-01-01
      • 2013-11-24
      • 2011-01-31
      相关资源
      最近更新 更多