我有一个复杂的文件,如下所示:
configuration {
step 58000
dt 2.00000000000000e+00
}
colvar {
name r
x 1.44869849559022e+01
}
0.00000000000000e+00 0.00000000000000e+00 0.00000000000000e+00
0.00000000000000e+00 0.00000000000000e+00 0.00000000000000e+00
hill {
step 1440
weight 1.00000000000000e-01
centers 1.47455750990065e+01 -1.69229380745887e+02
widths 1.25331413731550e+00 1.25331413731550e+00
}
hill {
step 1560
weight 1.00000000000000e-01
centers 1.47435719215456e+01 -1.70289673373179e+02
widths 1.25331413731550e+00 1.25331413731550e+00
}
hill {
step 1680
weight 1.00000000000000e-01
centers 1.47427376221419e+01 -1.68774767870364e+02
widths 1.25331413731550e+00 1.25331413731550e+00
}
我有兴趣从该文件中提取步长、重量和宽度,并将它们写入带有制表符分隔的新输出文件中。像这样 :-
#!step width1 width2 weight
1440 1.25331413731550e+00 1.25331413731550e+00 1.00000000000000e-01
我有以下内容,只写了步数和重量:-
awk ' b ~ /hill/ && a ~ /step/ && /weight/ {print v"\t"$2}{b=a; a=$0; v=$2}' input > output
我怎样才能将它扩展为写入宽度?
答案1
您可以使用 getline 函数读取下一行。
$ awk -vOFS='\t' '/^hill {/{
getline; st=$2
getline; we=$2
getline; getline; wd1=$2; wd2=$3
print st, we, wd1, wd2
}' file
1440 1.00000000000000e-01 1.25331413731550e+00 1.25331413731550e+00
1560 1.00000000000000e-01 1.25331413731550e+00 1.25331413731550e+00
1680 1.00000000000000e-01 1.25331413731550e+00 1.25331413731550e+00
答案2
为了清楚起见,扩展了以下解决方案:
awk '/hill/ { delete data }
/step/ { data["step"] = $2 }
/weight/ { data["weight"] = $2 }
/widths/ { data["widths"] = $2 "\t" $3;
print data["step"] "\t" data["weight"] "\t" data["widths"]; }' input
答案3
使用这一行命令解析您的输入文件:
echo -e "step\twidth1\t\t\twidth2\t\t\tweight" && grep -A4 ^hill widwei.txt | grep "step\|weight\|widths" | awk '{$1=""; print $0}' | awk 'NR%3{printf $0"";next;}1' | awk ' { t = $3; $3 = $2; $2 = t; print; } ' | awk ' { t = $4; $4 = $3; $3 = t; print; } ' | sed -e 's/^ //g' | sed -e 's/ /\t/g'
- 打印标题
- 乘坐接下来的 4 条线到山地段。
- 获取步长、重量和宽度值。
- 将它们打印在一行中。
- 交换列以获得您想要的格式。
- 删除剩余的开头空格并用制表符分隔。
答案4
awk -v RS="hill {" 'NF==11 {$1=$3=$5=$8=$11=""; print }' file
(使用 gnu awk;虽然很容易适应,但该解决方案对于格式变化并不稳健)
-v RS="hill {"
定义一个新的记录分隔符(RS)(默认情况下是行,现在是“山”段落)NF==11
...如果记录有 11 个字段$1=$3=$5=$8=$11="";
...删除文字print
...并打印提醒