在两列中打印每一秒的连续字段 - awk

时间:2016-02-10 13:05:47

标签: awk

假设以下文件

#zvview.exe
#begin Present/3
 77191.0000 189.320100          0          0          3          0111110 16    1
-8.072430+6-8.072430+6      77190          0          1         37111110 16    2
         37          2                                            111110 16    3
 8.115068+6 0.000000+0 8.500000+6 6.390560-2 9.000000+6 6.803440-1111110 16    4
 9.500000+6 1.685009+0 1.000000+7 2.582780+0 1.050000+7 3.260540+0111110 16    5
         37          2                                            111110 16   18

我想要做的是打印两列,第6行后面的字段。可以使用NR完成。棘手的部分如下:每个第二个字段应该放在一列中,并在符号前添加E,这样输出文件将如下所示

8.115068E+6 0.000000E+0
8.500000E+6 6.390560E-2
9.000000E+6 6.803440E-1
9.500000E+6 1.685009E+0
1.000000E+7 2.582780E+0
1.050000E+7 3.260540E+0

从输出文件中,您可以看到我希望$6只保留length($6)=10个字符。

如何在awk中完成?

3 个答案:

答案 0 :(得分:2)

可以在awk中完成所有操作,但使用unix工具集可能更容易

$ sed -n '6,7p' file | cut -c2-66 | tr ' ' '\n' | pr -2ats' '

8.115068+6 0.000000+0
8.500000+6 6.390560-2
9.000000+6 6.803440-1
9.500000+6 1.685009+0
1.000000+7 2.582780+0
1.050000+7 3.260540+0

以下是仅awk解决方案或比较

$ awk 'NR>=6 && NR<=7{$6=substr($6,1,10);
                      for(i=1;i<=6;i+=2) {f[++c]=$i;s[c]=$(i+1)}}
                  END{for(i=1;i<=c;i++) print f[i],s[i]}' file

8.115068+6 0.000000+0
8.500000+6 6.390560-2
9.000000+6 6.803440-1
9.500000+6 1.685009+0
1.000000+7 2.582780+0
1.050000+7 3.260540+0

也许是更短的版本,

$ awk 'NR>=6 && NR<=7{$6=substr($6,1,10); 
                      for(i=1;i<=6;i+=2) print $i FS $(i+1)}' file

8.115068+6 0.000000+0
8.500000+6 6.390560-2
9.000000+6 6.803440-1
9.500000+6 1.685009+0
1.000000+7 2.582780+0
1.050000+7 3.260540+0

要将格式转换为标准科学记数法,您可以将结果传递给 sed或在awk脚本中嵌入类似内容(使用gsub)。

... | sed 's/[+-]/E&/g'

8.115068E+6 0.000000E+0
8.500000E+6 6.390560E-2
9.000000E+6 6.803440E-1
9.500000E+6 1.685009E+0
1.000000E+7 2.582780E+0
1.050000E+7 3.260540E+0

答案 1 :(得分:2)

使用FIELDWIDTHS的GNU awk:

$ cat tst.awk
BEGIN { FIELDWIDTHS="9 2 9 2 9 2 9 2 9 2 9 2" }
NR>5 && NR<8 {
    for (i=1;i<NF;i+=4) {
        print $i "E" $(i+1), $(i+2) "E" $(i+3)
    }
}

$ awk -f tst.awk file
 8.115068E+6  0.000000E+0
 8.500000E+6  6.390560E-2
 9.000000E+6  6.803440E-1
 9.500000E+6  1.685009E+0
 1.000000E+7  2.582780E+0
 1.050000E+7  3.260540E+0

如果你真的想要摆脱领先的空白,那么有各种方法可以做到这一点(在相关领域最简单的是gsub(/ /,"",$<field number>))但是我把它们留在了里面,因为上面允许输出到如果/当您的数字以-开头时排队正确,就像他们在您的示例输入的第4行上所做的那样。

如果你没有GNU awk,那就得到它,因为你错过了很多非常有用的功能。

答案 2 :(得分:0)

我尝试使用substr将@karafka的答案结合起来,所以以下是诀窍!

awk 'NR>=6 && NR<=7{$6=substr($6,1,10);for(i=1;i<=6;i+=2) print substr($i,1,8) "E" substr($i,9) FS substr($(i+1),1,8) "E" substr($(i+1),9)}' file

,输出

8.115068E+6 0.000000E+0
8.500000E+6 6.390560E-2
9.000000E+6 6.803440E-1
9.500000E+6 1.685009E+0
1.000000E+7 2.582780E+0
1.050000E+7 3.260540E+0