Чтение определенных строк из входного файла

У меня есть входной файл с такой общей структурой. Я хочу только извлечь значения step и weight из блоков холмов и поместить их в выходной файл с помощью 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

Пожалуйста, помогите мне разобраться с этой проблемой.

Спасибо,

0
05.09.2016, 07:01
2 ответа

1) С sed

Предполагая, что step и вес встречаются в последовательных строках,

$ 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 / match, если строки содержат step
  • N , чтобы получить следующую строку

Примечание:

выше было протестировано на GNU sed 4.2.2 .Приведенное ниже может помочь в OS X и других версиях. См. этот Q&A на 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} сохраняет соответствие строки и второго поля
  • ~ / step / && / weight / , если предыдущая строка содержит step , а текущая строка содержит вес

] Предполагая, что все блоки hill аналогичны введенным данным, мы можем сопоставить три последовательные строки, чтобы ограничить сопоставление только блоками hill

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

Чтобы сохранить результаты, добавьте > output_filename до конца команды

Ссылка:

1
28.01.2020, 02:47

Более простой в использовании awk дважды: первый раз для извлечения блока hill {} и второй раз для извлечения значений шага / веса.

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

Эта команда будет работать только в том случае, если вес появится после шага , но не обязательно в последовательных строках.

0
28.01.2020, 02:47

Теги

Похожие вопросы