Прочитайте таблицу после определенной строки и введите количество экземпляров с awk

У меня есть таблица где-то в большом файле журнала, который выглядит следующим образом:

----------------------------
CARTESIAN COORDINATES (A.U.)
----------------------------
  NO LB      ZA    FRAG    MASS        X           Y           Z
   0 C     6.0000    0    12.011         -8.817666638854597         -4.911814574090662         58.264165798697491
   1 C     6.0000    0    12.011         -7.879568488830738         -4.388761616508626         55.950914108733443
   2 C     6.0000    0    12.011         -7.790669273242299         -4.339145245237274         60.527363919786708
   3 C     6.0000    0    12.011         -7.070247938157430         -3.937287748509576         62.694740665963295
   4 C     6.0000    0    12.011         -7.244178391763230         -4.034368638160922         53.748929835486599
   5 H     1.0000    0     1.008         -6.427462410780078         -3.581016558829315         64.562423911622218
   6 H     1.0000    0     1.008         -6.674286700050606         -3.718319003596096         51.850593400164620

--------------------------------
INTERNAL COORDINATES (ANGSTROEM)
--------------------------------

Я хочу сказать awk, чтобы найти CARTESIAN COORDINATES (A.U.), затем найти NO LB, затем начать чтение вторая переменная в каждой строке до тех пор, пока она не достигнет пробела до -----.

Итак, я буду читать все (элементы Carbon (C) Oxygen (O) Hydrogen (H )) C 's H' s и ... тогда я получаю, сколько C 's H.

У меня есть, и я могу сделать переменную типа [ f14] в этом случае может оказаться что-то вроде C3OH4, любых идей?

awk '
/CARTESIAN COORDINATES (A.U.)/ {fcart=1}
fcart &&
/  NO LB/ {scart=1}


/---------------------------/{exit}
' OFS="\t" "$FILENAME"
1
задан 29 September 2015 в 23:06

3 ответа

Еще одна awk-версия:

awk '/NO.*[[:blank:]]LB/,/INTERNAL COORDINATES/ { 
        if($1~/[0-9]/){count[$2]++;}} 
      END {for(i in count){printf "%s%s",i,count[i]}print ""} ' file 

Это своего рода смесь между ответом Серга и Хаосом. Он будет работать только между строками, соответствующими NO.*[[:blank:]]LB и INTERNAL COORDINATES. Массив count учитывает только строки, первое поле которых является числом.

Если ваш файл точно так же, как вы показываете, где последовательные блоки данных разделены пустой строкой, вы можете использовать режим абзаца Perl, который обрабатывает абзацы как строки: [ ! d3]

perl -00ne 'next unless /CARTESIAN COORDINATES \(A\.U\.\)/; 
            $count{$_}++ for (/\s+\d+\s+(\w+)\s/g); 
            print "$_$count{$_}" for keys(%count)' file 

Пояснение

-00: включить режим абзаца; next unless /CARTESIAN COORDINATES \(A\.U\.\)/; пропустить этот абзац, если он не соответствует CARTESIAN COORDINATES (A.U.); $count{$_}++ for (/\n\s+\d+\s+(\w+)\s/g): регулярное выражение ищет один или несколько пробельных символов (\s+), за которыми следуют одна или несколько цифр (\d+), один или несколько символов пробелов, а затем один или несколько символов слова (\w+) за которым следует символ пробела. Это должно идентифицировать все элементы. %count - хэш, ассоциативный массив. Он имеет ключи, и каждый ключ связан со значением. [F16] сохранит каждое из совпадений регулярного выражения выше как ключ в этом хэше и увеличит его значение на единицу каждый раз, когда он будет найден. Результатом является хэш, который хранит элементы и количество раз, когда каждый найден. print "$_$count{$_}" for keys(%count): для каждого из элементов (клавиши хеша %count) напечатайте элемент и количество раз, когда оно было найдено.

Запустите файл вашего примера, это возвращает:

$ perl -00ne 'next unless /CARTESIAN COORDINATES \(A\.U\.\)/; 
            $count{$_}++ for (/\s+\d+\s+(\w+)\s/g); 
            print "$_$count{$_}" for keys(%count)' file 
C5H2$

У этого нет последней строки новой строки, поэтому вы можете добавить его с помощью:

$ perl -00ne 'next unless /CARTESIAN COORDINATES \(A\.U\.\)/; 
                $count{$_}++ for (/\s+\d+\s+(\w+)\s/g); 
                print "$_$count{$_}" for keys(%count); print "\n"' file 
C5H2
4
ответ дан 23 May 2018 в 17:04

Вот несколько более простой код:

awk '/NO.*[[:blank:]]LB/,/INTERNAL COORDINATES/ { if ( $2 == "C")  counterC++; if ($2 == "H") counterH++  } END {print "C"counterC"H"counterH} ' coordinates.txt

Пример вывода:

$ awk '/NO.*[[:blank:]]LB/,/INTERNAL COORDINATES/ { if ( $2 == "C")  counterC++; if ($2 == "H") counterH++  } END {print "C"c>
C5H2
2
ответ дан 23 May 2018 в 17:04
  • 1
    большая проблема не искала конкретный C или H, просто смотрящий на второй элемент и видя, сколько раз он повторяется в той же форме, он может быть C2O3H5 или C3SiH3O – Raymond Ghaffarian Shirazi 29 September 2015 в 23:23
  • 2
    @RaymondGhaffarianShirazi Я вижу. Позвольте мне исправить это – Sergiy Kolodyazhnyy 29 September 2015 в 23:27
  • 3
    @RaymondGhaffarianShirazi будет хорошо, если код просто выводит число каждого элемента? Поскольку составление полной формулы, вероятно, будет слишком сложным для кода – Sergiy Kolodyazhnyy 29 September 2015 в 23:33
  • 4
    это нормально, код хаоса работает нормально, THX – Raymond Ghaffarian Shirazi 29 September 2015 в 23:42

Ответ хаоса очень хорошо работает, чтобы выполнить то, что вы хотите. Вот еще более простая альтернатива:

awk 'BEGIN{}
$2 ~ /^C$/ { countC++; } $2 ~ /^H$/ { countH++ }
END { print "C",countC,"H",countH; }' OFS="" file

Дает выход C5H2.

2
ответ дан 23 May 2018 в 17:04
  • 1
    большая проблема не искала конкретный C или H, просто смотрящий на второй элемент и видя, сколько раз он повторяется в той же форме, он может быть C2O3H5 или C3SiH3O – Raymond Ghaffarian Shirazi 29 September 2015 в 23:24
  • 2
    Обратите внимание, что нет причин для инициализации переменных 0 в блоке BEGIN. Вы можете просто использовать их напрямую: awk '$2 ~ /^C$/ { countC++; } $2 ~ /^H$/ { countH++ }END { print "C",countC,"H",countH; }' OFS="" file – terdon♦ 30 September 2015 в 02:21
  • 3
    @terdon Спасибо, что указали, что я тоже обновил свой ответ. – H. Freeze 30 September 2015 в 15:35
  • 4
    @RaymondGhaffarianShirazi Мой плохой, проверьте ответ хаоса, он отлично работает с этой целью – H. Freeze 30 September 2015 в 15:39

Другие вопросы по тегам:

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