Awk: работа с переменной в операторе if

Я пытаюсь понять, как awk работает с переменными в операторах if.

Вот текстовый файл игрушки:

$ cat myscript.sh 
#! /bin/bash

set -eu
set -o pipefail

IFS=$'\n\t'

for arg in $@; do
    echo "do something with file $arg"
done

Теперь я хочу awk напечатать самую длинную строку в файле. Я думал сделать так:

$  awk '{max = 0}{if (length($0) > max) {max = length($0)} else {}} END {print max}' myscript.sh 

Но это напечатает длину последней строки. Однако, когда я запускаю следующее:

awk '{if (length($0) > max) {max = length($0)} else {}}END{print max}' myscript.sh 

Результат правильный, и он печатает правильную длину 35.

Я действительно не могу понять, почему, когда я указываю переменную max перед оператором if, условие не распознается. Я уверен, что есть простое объяснение awk-gurus, но лично я его не вижу.

Спасибо

{max = 0} в первом коде устанавливает max на ноль перед каждой записью.
anubhava 28.05.2019 12:21

Я просто использовал ее как фиктивную переменную, а затем присваиваю ей следующие значения, если length если она длиннее, чем предыдущее max значение. Эта логика верна?

efrem 28.05.2019 12:28
awk 'length() > max{max = length()} END{print max}' file короче.
anubhava 28.05.2019 12:32

Спасибо, вот это я не понимаю, где мне определять переменную max? или в этом нет необходимости?

efrem 28.05.2019 12:34

Нет, не нужно определять это. Если вы действительно хотите инициализировать какую-либо переменную, поместите ее в блок BEGIN.

anubhava 28.05.2019 12:40
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
2 045
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете немного изменить первую команду, чтобы она работала:

awk 'BEGIN{max = 0}{if (length($0) > max) {max = length($0)} else {}} END {print max}' myscript.sh 

Таким образом, вы инициализируете переменную max в начале скрипта. Без оператора BEGIN max обновляется до 0 в каждой строке.

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

Variables in awk can be assigned either numeric or string values. The kind of value a variable holds can change over the life of a program. By default, variables are initialized to the empty string, which is zero if converted to a number.

С помощью этой команды:

awk '{if (length($0) > max) {max = length($0)} else {}}END{print max}' myscript.sh 

Awk инициализирует max значением 0 в первой строке, потому что вы сравниваете его с длиной ($0), которая является целым числом.

wrt Awk will initialize max to 0 at the first row because you are comparing it to length($0) which is an integer. - нет, не будет. Если это так, то запуск этой команды для пустого файла выведет 0, но вместо этого выведет нулевую строку. Когда length($0) > max выполняется впервые, max имеет тип числовой строки со значением ноль или ноль, это сравнение, который обрабатывается как числовой, поскольку он сравнивает число с числовым значением, но max не меняет свой тип или значение при эта точка.

Ed Morton 28.05.2019 15:07

Попробуйте запустить эти команды, чтобы увидеть это: seq 2 | awk '{print "max = " ( (max == 0) && (max == "") ? "zero-or-null" : max ); max=0}' и seq 2 | awk '{print "max = " ( (max == 0) && (max == "") ? "zero-or-null" : max ); max = ""}'. В gawk вы можете просто напечатать typeof(max), чтобы увидеть его тип в любой момент, например. echo "" | awk '{if (length($0) > max) {max = length($0)} print typeof(max)}' выведет unassigned.

Ed Morton 28.05.2019 15:13

@Corentin уже объяснил вашу проблему, поэтому вы должны оставить его / ее ответ как принятый, но просто к вашему сведению, правильный способ напечатать длину самой длинной строки в файле таков:

awk '{cur=length()} cur>max{max=cur} END{print max+0}' myscript.sh

Это гарантирует, что max будет числом, даже если все строки пусты, не вызывает length() несколько раз в строке и гарантирует, что вы получите числовой вывод, даже если ввод пуст (точно так же, как wc делает для пустых файлов).

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