Я новичок AWK. У меня есть следующий мотив в огромном файле.

~ Gradients ~
~   x               y            z      ~
~~ 
~ H         1      0.00781      0.00108      0.00038 ~
~ H         2      0.01271     -0.01507      0.02839 ~
~ C         1     -0.05015     -0.01803      0.01588 ~
~ O         1      0.01733      0.03089     -0.04611 ~
~ O         2      0.01230      0.00114      0.00147 ~

Мне нужно извлечь эти цифры (XYZ):

0.00781      0.00108      0.00038
0.01271     -0.01507      0.02839
-0.05015     -0.01803      0.01588
0.01733      0.03089     -0.04611 
0.01230      0.00114      0.00147

Я написал следующий скрипт:

awk '/z ~/ {for(i=-2; i<=3; i++) {getline; print $4, $5, $6}}' filename

Но это дает мне пустую строку из-за строки "~~".

Я хотел бы игнорировать эту строку и получает только столбцы XYZ

xyz
xyz
xyz
xyz 

и т.д. без каких-либо пустых строк ...

Кто-нибудь может мне помочь, пожалуйста?

2 ответа2

1

Можете ли вы объяснить более четко , что именно вы пытаетесь сделать?  Похоже, вы пытаетесь вывести значения x, y и z ($4 , $5 и $6) из следующих шести строк после строки, содержащей литерал z за которым следует ~ .  Но это не имеет особого смысла - если у вас нет повторяющегося шаблона заголовка, пяти строк данных, другого заголовка, еще пяти строк данных и т.д. - и, если это так, вам действительно нужно это объяснить.  И если это то, что вы пытаетесь сделать, почему вы делаете это for(i=-2; i<=3; i++) вместо for(i=1; i<=6; i++) .

И это не очень хороший способ использовать getline .

Если я правильно понимаю вашу цель, все, что вам нужно, это

awk 'NF==7 {print $4, $5, $6}' filename

Это выведет 4-е, 5-е и 6-е поля (x, y и z) из каждой строки, имеющей семь полей, и игнорирует все остальное.

0

Ваш вопрос сбивает с толку, потому что ваши данные имеют строку заголовка, оканчивающуюся на z      ~ и ваша команда ищет /z ~/ , поэтому они не должны совпадать.  Но, возможно, это на самом деле zTab~ в обоих местах.

Для простоты я буду использовать /z *~/ , чтобы соответствовать z , затем любое количество пробелов, а затем ~ .  Продолжайте и продолжайте использовать любую строку поиска, которая работает для вас.

Вы пояснили в комментарии, что хотите напечатать значения x, y и z из 2-й, 3-й, 4-й, 5-й и 6-й строк после строки заголовка, содержащей z   ~ .  Вот способ сделать это в awk:

awk '
        /z *~/          { counter=1; next }
        counter > 1     { print $4, $5, $6 }
        counter == 6    { counter = 0 }
        counter > 0     { counter++ }
    ' filename
  • /z *~/ { counter=1; next } говорит, что когда мы видим строку, содержащую z   ~ , мы устанавливаем счетчик в 1.  Это будет использоваться для подсчета следующих шести строк.  Используйте next команду, чтобы больше не обрабатывать эту строку - мы не хотим даже рассматривать возможность печати строки заголовка.
  • counter > 1 { print $4, $5, $6 } печатает x, y и z из строк, где counter > 1 .  Обратите внимание, что это не тестирование counter > 0 или counter >= 1 , поэтому он пропускает 1-ю строку после заголовка и печатает 2-ю, 3-ю, 4-ю, 5-ю и 6-ю строки.
  • counter == 6 { counter = 0 } говорит, что когда counter достигает 6, мы закончили с этим «мотивом», поэтому мы устанавливаем counter на ноль.
  • counter > 0 { counter++ } просто говорит, что, пока мы находимся в «мотиве», мы должны увеличивать (добавлять единицу) counter для каждой строки.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .