1

I have a complicated file, which looks like this :

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
}  

I am interested in extracting steps, weight and widths from this file and writing them in a new output file with a tab separation. Just like this :-

#!step   width1                    width2             weight
1440   1.25331413731550e+00  1.25331413731550e+00   1.00000000000000e-01

I have the following, which only writes steps and weight :-

awk ' b ~ /hill/ && a ~ /step/ && /weight/ {print v"\t"$2}{b=a;  a=$0; v=$2}' input > output

How can I extend it to write widths as well ?

1

you can use getline function that read in nextline.

$ 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
1

The following solution is expanded for the sake of clarity:

 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
1

Parsing your input file with this one line command:

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'
  1. Print the header
  2. Take the next 4 lines to hill section.
  3. Take the step, weight and widths values.
  4. Print them in one line.
  5. Swap the columns in order to get your desired format.
  6. Delete remaining beginning spaces and separate with tabs.
1
awk -v RS="hill {"    'NF==11 {$1=$3=$5=$8=$11=""; print }' file

(using gnu awk; although easily adaptable, this solution is not robust to format variations)

  • -v RS="hill {" defines a new record separator (RS) (by default it was lines, now is "hill" paragraphs)
  • NF==11 ...if the recors has 11 fields
  • $1=$3=$5=$8=$11=""; ... remove the literals
  • print ... and print the reminder

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.