У меня есть входной файл с такой общей структурой. Я хочу только извлечь значения 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
Пожалуйста, помогите мне разобраться с этой проблемой.
Спасибо,
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
до конца команды
Ссылка:
Более простой в использовании awk дважды: первый раз для извлечения блока hill {}
и второй раз для извлечения значений шага / веса.
awk '/hill *{/,/}/ {print}' \
| awk '$1 == "step" { st = $2 }; $1 == "weight" { print st "\t" $2}'
Эта команда будет работать только в том случае, если вес
появится после шага
, но не обязательно в последовательных строках.