Как использовать `awk`, чтобы я мог условно изменить только одно или два поля в строке? - PullRequest
2 голосов
/ 22 ноября 2011

У меня есть разделенный табуляцией файл с 16 полями.Могу ли я использовать awk для условного изменения одного или полей и вывода всей строки в качестве вывода?Например, в зависимости от значения в первом поле, я хочу сказать добавить конкретное число в поле 4 и так далее.Но в качестве вывода я должен напечатать всю строку.Если да, я хотел бы знать, как.

Ответы [ 3 ]

6 голосов
/ 22 ноября 2011

Да, вот подход:

awk '$1 == "ALTER" { $5=$5+5 } 1'

С файлом примера etuardu получается

ALTER xx yy zz 15 10
NOALT aa bb cc 20 20
ALTER 11 22 33 35 30

Вот как это работает. Есть два случая, выраженные в шаблонах и действиях awk. В первом шаблон является тестом первого поля, чтобы определить, равно ли оно "ALTER", и вызывает действие, которое изменяет пятое поле, если шаблон оценивается как true. Второй паттерн - это последний 1; это всегда так, поэтому неявное действие print выполняется.

Одна из особенностей этого решения: разделители полей, считываемые на входе, не обязательно должны быть разделителями на выходе. В приведенной выше простой форме разделители полей от входных данных считаются пробелами, а одиночные пробелы записываются в выходные данные; установите FS и OFS на определенные значения, если это не то, что вы хотите. Однако только строки, в которых поле было изменено, будут иметь новые разделители полей, поэтому нулевая операция, такая как '$ 1 = $ 1', приведет к перестроению всех записей (это удобный способ изменить разделители полей, используя только $1=$1 ).

1 голос
/ 22 ноября 2011

Как насчет этого (образец файла взят из @etuardu) -

awk '{if($1=="ALTER") {$5=$5+1;print"\n";for (i=1;i<=NF;i++) printf $i" ";} else print "\n"$0}' input_file | sed '/^$/d'
  • Проверьте, какую строку нужно изменить, используя оператор if.
  • Если ожидаемое поле найдено, внесите изменения, например. $ 5 = $ 5 + 1 ... и так далее и тому подобное.
  • Запустите цикл for, повторив цикл в зависимости от количества полей.
  • Напечатайте поля, которые будут включать обновленные поля.
  • Если ожидаемое поле не найдено, запустите цикл else.
  • sed удалит все пустые строки, которые были созданы из-за новых строк.

Образец:

[jaypal~/Temp]$ cat text8
NOALT aa bb cc 20 20
ALTER xx yy zz 10 10
ALTER xx yy zz 10 10
NOALT aa bb cc 20 20
ALTER 11 22 33 30 30

[jaypal~/Temp]$ awk '{if($1=="ALTER") {$5=$5+1;print"\n";for (i=1;i<=NF;i++) printf $i" ";} else print "\n"$0}' text8 | sed '/^$/d'
NOALT aa bb cc 20 20
ALTER xx yy zz 11 10 
ALTER xx yy zz 11 10 
NOALT aa bb cc 20 20
ALTER 11 22 33 31 30
1 голос
/ 22 ноября 2011

Да. Это пример использования (возможно, не самый умный):

etuardu@subranu:~$ cat sample.txt 
ALTER xx yy zz 10 10
NOALT aa bb cc 20 20
ALTER 11 22 33 30 30
etuardu@subranu:~$ awk '{ if ($1=="ALTER") print $1,$2,$3,$4,$5+1,$6-1; else print $0 }' sample.txt 
ALTER xx yy zz 11 9
NOALT aa bb cc 20 20
ALTER 11 22 33 31 29

Пожалуйста, обратитесь к man awk или некоторому онлайн-учебнику (их достаточно) для получения дополнительной информации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...