从输入文件中读取特定行

从输入文件中读取特定行

我有一个具有这种一般结构的输入文件。我只想从山块中提取值步长和权重,并使用 awk/sed/grep 将它们放入输出文件中。山块在输入文件中以类似的方式排列。

编辑:我正在使用 MAC OSX。

 configuration {
 step         5000
 dt 2.000000e+00
 }

colvar {
name d1
x  1.70882305580118e+01
v  0.00000000000000e+00
}

1.85104129628346e-02 9.71380137561312e-02 4.00538287370335e-02
1.25662994200839e-02 9.88655406140091e-02 1.41657757894898e-01

hill {
step            0
weight    1.00000000000000e-01
centers   1.23563844380284e+02
widths    1.25331413731550e+00
}
 hill {
 step          100
 weight    1.00000000000000e-01
centers   1.19065310650377e+02
widths    1.25331413731550e+00
}

通过其他一些答案,我设法找到了一些帮助:-

 sed 's/^.*weight//' diol_colvar.colvars.state > hill.txt
 sed 's/^.*step//' diol_colvar.colvars.state > hill.txt

遗憾的是这并没有按照我想要的方式工作。

我希望我的输出是这样的:-

  0     1.00000000000000e-01
  100   1.00000000000000e-01

请帮我解决这个问题。

谢谢,

答案1

1) 与sed

假设stepweight出现在连续行中,

$ sed -nE '/step/{N;s/.*step\s+(\S+).*\n.*weight\s+(\S+).*/\1\t\2/p}' ip.txt 
0   1.00000000000000e-01
100 1.00000000000000e-01
  • -nE默认情况下不打印行并使用扩展正则表达式
  • /step/匹配如果行包含step
  • N得到下一行

笔记:

以上是在 上测试过的GNU sed 4.2.2。以下内容可能对 OS X 和其他版本有所帮助。看关于 SO 的问答详细信息,要点是\s可能与 GNU sed 工作方式不同

sed -nE '/step/{N;s/.*step[[:space:]]+([^[:space:]]+).*\n.*weight[[:space:]]+([^[:space:]]+).*/\1\t\2/p}' ip.txt

2) 与awk

$ awk 'a ~ /step/ && /weight/{print v"\t"$2} {a=$0; v=$2}' ip.txt 
0   1.00000000000000e-01
100 1.00000000000000e-01
  • {a=$0; v=$2}保存该行和第二个字段
  • a ~ /step/ && /weight/step如果上一行包含并且当前行包含则匹配weight

假设hill块都与给定的输入相似,我们可以匹配三个连续行以将匹配限制为仅hill

awk 'b ~ /hill/ && a ~ /step/ && /weight/{print v"\t"$2} {b=a; a=$0; v=$2}' ip.txt

要保存结果,请添加> output_filename到命令末尾

参考:

答案2

使用 awk 两次更容易:第一次提取hill { }块,第二次提取步长/权重值。

awk '/hill *{/,/}/ {print}' \
   | awk '$1 == "step" { st = $2 }; $1 == "weight" { print st "\t" $2}'

weight该命令仅在后面出现step但不需要连续行时才有效。

相关内容