Поскольку производительность важна, тестирование на 4 доллара один раз будет быстрее, чем тестирование дважды:
awk '$4{print $0, $2/$4, $3/$4; next} {print $0, 0, 0}' Input_file
Компромиссом для повышения производительности является дублирующий код (2 print $0
с), но это, очевидно, минимально в этом case и все решения имеют некоторое дублирование кода.
Мне было любопытно, и я решил определить время всех трех текущих ответов (мои, @ Ravinders и @ Inians ). Вот результаты 3-го запуска синхронизации с использованием GNU awk на MacOS с 10-миллионным строчным файлом, сгенерированным путем запуска awk '{for (i=1; i<=2000000; i++) print}' file > file10m
на OP, предоставленных в качестве примера ввода.
$ time awk '$4{print $0, $2/$4, $3/$4; next} {print $0, 0, 0}' file10m >/dev/null
real 0m10.087s
user 0m10.009s
sys 0m0.054s
$ time awk '{print $0, ($4 ? $2/$4 : 0), ($4 ? $3/$4 : 0)}' file10m >/dev/null
real 0m10.329s
user 0m10.249s
sys 0m0.060s
$ time awk '{ $(NF+1) = ($4 ? $2/$4 :0); $(NF+1) = ($4 ? $3/$4 :0) }1' file10m >/dev/null
real 0m11.293s
user 0m11.208s
sys 0m0.063s
и с использованием awk по умолчанию OSX:
$ time /usr/bin/awk '$4{print $0, $2/$4, $3/$4; next} {print $0, 0, 0}' file10m >/dev/null
real 0m13.383s
user 0m13.240s
sys 0m0.123s
$ time /usr/bin/awk '{print $0, ($4 ? $2/$4 : 0), ($4 ? $3/$4 : 0)}' file10m >/dev/null
real 0m14.293s
user 0m14.082s
sys 0m0.161s
$ time /usr/bin/awk '{ $(NF+1) = ($4 ? $2/$4 :0); $(NF+1) = ($4 ? $3/$4 :0) }1' file10m >/dev/null
real 0m15.668s
user 0m15.516s
sys 0m0.130s
, поэтому подход Inians в этих тестах был примерно на 12-17% медленнее, чем у меня, а Ravinders примерно на 2-7% медленнее с различными улучшениями скорости в зависимости от версии awk.
Я также тестировал awk '{print $0, ($4 ? $2/$4 OFS $3/$4 : 0 OFS 0)}'
но обнаружил, что он немного медленнее моего предложения в GNU awk и еще медленнее в OSX awk (аналогично Ravinders), вероятно, из-за конкатенации строк. Использование жесткого кода "0 0"
для остальной части троичного во избежание конкатенации в этом отрезке дало небольшое улучшение в скорости выполнения. С gawk:
$ time awk '{print $0, ($4 ? $2/$4 OFS $3/$4 : "0 0")}' file10m >/dev/null
real 0m10.145s
user 0m10.058s
sys 0m0.064s
и с BSD awk:
$ time /usr/bin/awk '{print $0, ($4 ? $2/$4 OFS $3/$4 : "0 0")}' file10m >/dev/null
real 0m13.993s
user 0m13.818s
sys 0m0.139s
, но это все же не так быстро, как мое первоначальное предложение выше, и я не уверен, что нужно жестко кодировать это Строка, включающая то, на что, как вы надеетесь, будет иметь значение OFS, является компромиссом.