我有一个* .xvg格式的文件 它包含六列,每列有500个数字 除时间列(第一列)外,所有其他列都包含浮点数。
我想以相同的格式生成输出文件,其中这些列被转换为行,每个数字用空格分隔。
我用C编写了一个程序,对我来说很好用,但我正在寻找一种使用awk或sed的替代方法,这样我就可以做到这一点。
我对这些脚本语言完全陌生。在之前提出的问题中,我找不到任何相关的答案。所以,如果有人能帮助我完成这项任务,我将不胜感激。
输入文件如下所示: -
# This file was created Thu Oct 1 17:18:10 2015
# by the following command:
# /home/durba/gmx455/bin/mdrun -np 1 -deffnm md0 -v
#
@ title "dH/d\xl\f{}, \xD\f{}H"
@ xaxis label "Time (ps)"
@ yaxis label "(kJ/mol)"
@TYPE xy
@ subtitle "T = 200 (K), \xl\f{} = 0"
@ view 0.15, 0.15, 0.75, 0.85
@ legend on
@ legend box on
@ legend loctype view
@ legend 0.78, 0.8
@ legend length 2
@ s0 legend "dH/d\xl\f{} \xl\f{} 0"
@ s1 legend "\xD\f{}H \xl\f{} 0.05"
0 19.3191 1.16531 1.8 -447.07 -47.07
2 -447.072 -17.6454 1.5 -17.633 -1.33
4 -17.633 -0.446508 1.3 -75.455 -5.45
6 -75.4555 -2.83981 1.4 -28.724 -28.4
8 -28.7246 -0.884639 1.5 -41.877 -14.87
10 -41.8779 -1.45569 2.8 -43.685 -3.685
12 -43.6851 -1.4797 -3.1 -91.651 -91.651
14 -91.6515 -3.52492 -3.5 -61.135 -1.135
16 -61.1356 -2.30129 -3.2 -48.847 -48.47
输出文件应如下所示: -
# This file was created Thu Oct 1 17:18:10 2015
# by the following command:
# /home/durba/gmx455/bin/mdrun -np 1 -deffnm md0 -v
#
@ title "dH/d\xl\f{}, \xD\f{}H"
@ xaxis label "Time (ps)"
@ yaxis label "(kJ/mol)"
@TYPE xy
@ subtitle "T = 200 (K), \xl\f{} = 0"
@ view 0.15, 0.15, 0.75, 0.85
@ legend on
@ legend box on
@ legend loctype view
@ legend 0.78, 0.8
@ legend length 2
@ s0 legend "dH/d\xl\f{} \xl\f{} 0"
@ s1 legend "\xD\f{}H \xl\f{} 0.05"
0 2 4 6 8 10 12
19.3191 -447.072 -17.633 -17.633 -75.4555 -28.7246 -41.8779 -43.6851 -91.6515 -61.1356
1.16531 -17.6454 -0.446508 -2.83981 -0.884639 -1.45569 -1.4797 -3.52492 -2.30129
1.8 1.5 1.3 1.4 1.5 2.8 -3.1 -3.5 -3.2
-447.07 -17.633 -75.455 -28.724 -41.877 -43.685 -91.651 -61.135 -48.847
-47.07 -1.33 -5.45 -28.4 -14.87 -3.685 -91.651 -1.135 -48.47
请注意,以“#”和“@”开头的行在两个文件中应该相同。
答案 0 :(得分:3)
让我们考虑一下这个测试文件:
$ cat file
123 1.2 1.3 1.4 1.5
124 2.2 2.3 2.4 2.5
125 3.2 3.3 3.4 3.5
将列转换为行:
$ awk '{for (i=1;i<=NF;i++)a[i,NR]=$i} END{for (i=1;i<=NF;i++) for (j=1;j<=NR;j++) printf "%s%s",a[i,j],(j==NR?ORS:OFS)}' file
123 124 125
1.2 2.2 3.2
1.3 2.3 3.3
1.4 2.4 3.4
1.5 2.5 3.5
for (i=1;i<=NF;i++)a[i,NR]=$i
当我们遍历每一行时,我们将值保存在数组a
中。
END{for (i=1;i<=NF;i++) for (j=1;j<=NR;j++) printf "%s%s",a[i,j],(j==NR?ORS:OFS)}
在我们到达文件末尾之后,如果我们位于行中间或输出记录分隔符({{1}),则打印每个值后跟输出字段分隔符(OFS
) })如果我们在行的末尾。
如果你喜欢你的代码分布在几行:
ORS
在修订后的问题中,文件开头的行以awk '
{
for (i=1;i<=NF;i++)
a[i,NR]=$i
}
END{
for (i=1;i<=NF;i++)
for (j=1;j<=NR;j++)
printf "%s%s",a[i,j],(j==NR?ORS:OFS)
}
' file
或@
开头,不会被更改。在这种情况下:
#
答案 1 :(得分:1)
这可能适合你(GNU sed):
sed -r 'H;$!d;x;:a;h;s/\n(\S+)[^\n]*/\1 /g;s/ $//p;g;s/\n\S+ ?/\n/g;ta;d' file
将文件拖入保留空间(HS),删除模式空间(PS),直到满足文件结束条件。在文件结束时交换PS用于PS。将PS复制到HS,然后删除除第一个字段后的所有字段,其中第一个字段后跟一个空格全局。删除最后一个空格并打印该行。然后从HS调用该行的副本并执行相反的操作。如果任何替换成功,则重复该过程,直到只有换行符存在。删除不需要的换行符。
自从第一次回答原始问题后发生了变化。下面的新解决方案使用基本相同的方法来迎合新问题:
sed -r '/^[0-9]/{s/ +/ /g;H};//!p;$!d;x;:a;h;s/\n(\S+)[^\n]*/\1 /g;s/ $//p;g;s/\n\S+ ?/\n/g;ta;d' file