在块数据集中增加特定列的值并循环几次

时间:2019-02-23 11:56:09

标签: awk sed vi

我正在尝试按照上述顺序生成巨大的数据集。

4 0 1 642 643
4 642 643 1283 12
4 1283 1284 1924 1925
4 1924 1925 2565 2566
4 2565 2566 3206 3207
4 3206 3207 3847 3848
4 3847 3848 4488 4489
4 4488 4489 5129 5130

4 1 2 643 644
4 643 644 1284 1285
4 1284 1285 1925 1926
4 1925 1926 2566 2567
4 2566 2567 3207 3208
4 3207 3208 3848 3849
4 3848 3849 4489 4490
4 4489 4490 5130 5131

4 2 3 644 645
4 644 645 1285 1286
4 1285 1286 1926 1927
4 1926 1927 2567 2568
4 2567 2568 3208 3209
4 3208 3209 3849 3850
4 3849 3850 4490 4491
4 4490 4491 5131 5132

描述:有5列,第一列的常量为'4'。一个块中有8行(数据由空白行分隔)。

现在,我的想法是将前一个块(从1-8行开始)复制到10-17行,并将2-5列中的数字加1。此过程(现在必须将10-17行复制到19-27行中,并且将第2 -5列必须增加1)必须进行大约640次迭代才能生成我所需的集合。

有人可以建议我如何生成这种类型的数据集吗?

5 个答案:

答案 0 :(得分:1)

这可能对您有用(GNU sed和bash):

cat <<\!>file
4 0 1 642 643
4 642 643 1283 12
4 1283 1284 1924 1925
4 1924 1925 2565 2566
4 2565 2566 3206 3207
4 3206 3207 3847 3848
4 3847 3848 4488 4489
4 4488 4489 5129 5130

!

for n in {0..640}; do sed 's/\S\+/$((&+'$n'))/2g;s/.\+/printf "%d %d %d %d %d" &/e' file;done

回想起来,这也将起作用:

for n in {0..640}; do sed 's/\S\+/$((&+'$n'))/2g;s/.\+/echo "&"/e' file;done  

答案 1 :(得分:1)

$ cat tst.awk
{
    for (fldNr=1; fldNr<=NF; fldNr++) {
        flds[NR,fldNr] = $fldNr
    }
}
END {
    maxRecs = 3
    for (recNr=1; recNr<=maxRecs; recNr++) {
        for (lineNr=1; lineNr<=NR; lineNr++) {
            printf "%s", flds[lineNr,1]
            for (fldNr=2; fldNr<=NF; fldNr++) {
                printf " %s", flds[lineNr,fldNr]+(recNr-1)
            }
            print ""
        }
        print ""
    }
}

$ cat file
4 0 1 642 643
4 642 643 1283 12
4 1283 1284 1924 1925
4 1924 1925 2565 2566
4 2565 2566 3206 3207
4 3206 3207 3847 3848
4 3847 3848 4488 4489
4 4488 4489 5129 5130

$ awk -f tst.awk file
4 0 1 642 643
4 642 643 1283 12
4 1283 1284 1924 1925
4 1924 1925 2565 2566
4 2565 2566 3206 3207
4 3206 3207 3847 3848
4 3847 3848 4488 4489
4 4488 4489 5129 5130

4 1 2 643 644
4 643 644 1284 13
4 1284 1285 1925 1926
4 1925 1926 2566 2567
4 2566 2567 3207 3208
4 3207 3208 3848 3849
4 3848 3849 4489 4490
4 4489 4490 5130 5131

4 2 3 644 645
4 644 645 1285 14
4 1285 1286 1926 1927
4 1926 1927 2567 2568
4 2567 2568 3208 3209
4 3208 3209 3849 3850
4 3849 3850 4490 4491
4 4490 4491 5131 5132

只需将maxRecs=3更改为maxRecs=640或您喜欢的任何值。

答案 2 :(得分:1)

使用Perl单线版

 perl -0777 -ne ' while( $i++<3) { s/(?!^)(\d+)/$1+1/gme; print "$_\n" } '

具有给定的输入

$ cat saideep.txt
4 0 1 642 643
4 642 643 1283 12
4 1283 1284 1924 1925
4 1924 1925 2565 2566
4 2565 2566 3206 3207
4 3206 3207 3847 3848
4 3847 3848 4488 4489
4 4488 4489 5129 5130

$ perl -0777 -ne ' while( $i++<3) { s/(?!^)(\d+)/$1+1/gme; print "$_\n" } ' saideep.txt
4 1 2 643 644
4 643 644 1284 13
4 1284 1285 1925 1926
4 1925 1926 2566 2567
4 2566 2567 3207 3208
4 3207 3208 3848 3849
4 3848 3849 4489 4490
4 4489 4490 5130 5131

4 2 3 644 645
4 644 645 1285 14
4 1285 1286 1926 1927
4 1926 1927 2567 2568
4 2567 2568 3208 3209
4 3208 3209 3849 3850
4 3849 3850 4490 4491
4 4490 4491 5131 5132

4 3 4 645 646
4 645 646 1286 15
4 1286 1287 1927 1928
4 1927 1928 2568 2569
4 2568 2569 3209 3210
4 3209 3210 3850 3851
4 3850 3851 4491 4492
4 4491 4492 5132 5133


$

答案 3 :(得分:0)

这些vi命令调用awk来执行任务:


:map z G{yGPG{!}awk '{for(i=NF;i>1;--i)++$i;print}' Ctrl + V CR CR 1GO ESC 640iz ESC "add@a


  • :map z (…) CR CR 定义了宏z
  • G{yGP复制了文件的最后一段
  • G{!}在最后一段执行awk
    • for(i=NF;i>1;--i)++$i;递增除第一个以外的所有字段
    • print修改后的行
  • 1GO ESC 640iz ESC 准备640个z的调用
  • "add@a运行准备好的命令

答案 4 :(得分:0)

以下bash脚本按照问题中的说明进行操作。

#!/bin/bash
for k in {1..639}
do
 echo "$k th iteration"
 tail -8 MWE.txt > i
 awk '{print $1, $2+1, $3+1, $4+1, $5+1}' i > j
 cat j >> MWE.txt
done

请注意,当我提供第一组数据(最初的8行数据)时,我将循环计数器变量“ k”增加到639。