Процесс последняя строка сначала с помощью awk

Использование восьмеричных кодов имеет два преимущества, о которых я могу думать, ни один из которых не настолько огромен:

  1. Они короче, легче ввести.
  2. Несколько вещей только понимают их, и если Вы обычно будете использовать их, то Вы не будете царапать голову (или работать к документации) при столкновении с тем. Например, необходимо использовать восьмеричный для chmod в Perl или C.

Иногда действительно простые утилиты не будут обрабатывать "дружественные" версии; особенно в пространствах пользователя не-GNU.

Далее, некоторые утилиты, выложенные восьмеричный. Например, если Вы работаете umask для наблюдения, каков текущий umask он выложит его в восьмеричном (хотя в ударе, umask -S делает символьный).

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

11
20.12.2012, 00:51
3 ответа

Можно сделать это как решение с двумя передачами в awk:

awk 'FNR == NR { n = $2; next } { print $1, $2/n }' infile infile

Если Ваша версия awk поддерживает блок ENDFILE (например, GNU awk 4 +), можно сделать это как это:

awk 'ENDFILE { n = $2 } FNR != NR { print $1, $2/n }' infile infile

Обратите внимание, что более эффективно seek в конец файла увидели ответ camh в первый раз.

Объяснение

Первый пример работает путем запоминания предыдущего $2, т.е. это только оценено когда счетчик местной линии (FNR) равно глобальному счетчику строки (NR). next управляйте пропусками к следующей строке, в этом случае она гарантирует, что последний блок только оценен, когда второй аргумент анализируется.

Второй пример имеет подобную логику, но использует в своих интересах блок ENDFILE, который оценен, когда конец входного файла достигнут.

5
27.01.2020, 19:58
  • 1
    Первый пример хорошо работает, второй не делает $ awk --version GNU Awk 3.1.8. Можно ли, возможно, включить очень маленькое объяснение, как два входных файла обрабатываются и что next ? –  Bernhard 19.12.2012, 10:16
  • 2
    @Bernhard: посмотрите редактирование –  Thor 19.12.2012, 10:33

Если Ваш источник данных является файлом, который может быть считан многократно (т.е. это не поток), необходимо сначала использовать tail(1) для получения данных, Вы хотите от последней строки и передачи это к awk для ее последовательной обработки файла. tail будет стремиться в конец файла считать последнюю строку, не будучи должен считать все данные перед ним.

awk -v norm=$(tail -n 1 file | cut -d' ' -f2) '{print $1, $2/norm}' file

Это будет большой победой на больших файлах, где целый файл не поместится в кэш-буфер (значение, что это должно было бы быть считано из диска дважды, однажды для каждой передачи), и поможет до меньшей степени, не будучи должен просканировать вход для получения до последней строки. Меньшие файлы не могут показать много различия подходу с двумя передачами.

6
27.01.2020, 19:58

Вы могли загрузить их в массив и считать его назад:

awk '{x[i++]=$0} END{for (j=i-1; j>=0;) print x[j--] }'

Вы могли сделать это более эффективно, но это отчасти иллюстрирует почему awk не правильный инструмент для этого. Продолжите использовать tac где это возможно, GNU tac является обычно самым быстрым из множества инструментов для этого задания.

3
27.01.2020, 19:58
  • 1
    я соглашаюсь, с помощью a for- циклы в awk не решение. –  Bernhard 19.12.2012, 10:17

Теги

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