приоритет оператора awk `!a[$0]++`

В ваших репозиториях упоминается только Buster, а набор пакетов mysql++не является частью Buster, потому что упаковка содержит ошибки (см.#871302 и#919377).

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

Я бы не рекомендовал проводить тестирование на сервере, особенно сейчас — тестирование заморожено в связи с подготовкой к следующему выпуску Debian, поэтому обновления (, включая исправления безопасности ), могут занять больше времени, чем обычно. сделал доступным там.

1
07.07.2020, 23:36
3 ответа

Я полагаю, мы можем согласиться с тем, что a[$0]имеет здесь наивысший приоритет (*), так что мы можем просто упростить это как x.

Я собираюсь доказать, что то, что вы прочитали, верно, что ++имеет более высокий приоритет, чем !, поэтому они должны быть равны:

$ awk 'BEGIN{ x=123; tmp = !x++;  print tmp, x; }'
0 124
$ awk 'BEGIN{ x=123; tmp = !(x++);  print tmp, x; }'
0 124

И это действительно так. !x++принимает значение x, возвращает его и затем увеличивает. Возвращаемое значение 123инвертируется, что дает 0. Увеличенное значение можно позже найти в x.

Но давайте попробуем и другую возможность, которая !связывает крепче:

$ awk 'BEGIN{ x=123; tmp = (!x)++;  print tmp, x; }'
awk: cmd. line:1: BEGIN{ x=123; tmp = (!x)++;  print tmp, x; }
awk: cmd. line:1:                           ^ syntax error

Ну, упс. Сейчас,это не может работать, так как !сначала примет значение x, а затем инвертирует его, возвращая 0. Теперь предполагается, что ++увеличивает это, и сохраняет результат обратно . Но 0— это просто значение, а не переменная, его нельзя сохранить. Отсюда ошибка. (Что-то вроде (1+2)++выдаст ту же ошибку.)

Следовательно, ++имеет более высокий приоритет, просто у него есть скрытый побочный эффект, который не виден из возвращаемого значения.

(*оператор подписки не появляется в таблице приоритетов в стандарте, в отличие от таблиц приоритетов операторов C , но если бы он имел более низкий приоритет, выражение действительно было бы не работает.)

4
18.03.2021, 23:21

Демо:

$ cat file
1 a
2 b
1 c
2 d
3 e
$ awk '!a[$1]++' file
1 a
2 b
3 e

++происходит первым. Поскольку это приращение поста -, для первой строки a[$1]++увеличивает значение a[1], но возвращает ноль, а отрицание меняет это значение на true, и первая строка печатается. То же самое со 2-й строкой. Для третьей строки a[1] уже имеет значение 1, приращение post -устанавливает значение равным 2 и возвращает 1, что с отрицанием равно false.


Справочная страница mawk стала более понятной:

   New expressions are composed with the following operators in order of increasing
   precedence.

        assignment          =  +=  -=  *=  /=  %=  ^=
        conditional         ?  :
        logical or          ||
        logical and         &&
        array membership    in
        matching       ~   !~
        relational          <  >   <=  >=  ==  !=
        concatenation       (no explicit operator)
        add ops             +  -
        mul ops             *  /  %
        unary               +  -
        logical not         !
        exponentiation      ^
        inc and dec         ++ -- (both post and pre)
        field               $
3
18.03.2021, 23:21

Оператор ++отличается тем, что он возвращает два значения (или воздействует на два значения ).

  1. Содержимое переменной увеличивается (на1). Либо pre, либо post. Для следующего использования переменной .

  2. На результат операции влияет и то, что в:

  • pre-incrementзначение операции принимает значение переменной , уже увеличенное . Или, другими словами, приращение переменной происходит до ее использования.

  • post-incrementзначение операции принимает значение переменной без приращения . Или, другими словами, приращение переменной происходит после ее использования.

Простой способ увеличения переменной подразумевает:

  1. Загрузить значение переменной (из памяти )в один регистр (A ).
  2. Увеличение значения переменной внутри регистра (A ).
  3. Сохраните значение в регистре обратно в ячейку памяти переменной.

Для понимания ++требуется два регистра.

  1. Загрузить значение переменной (из памяти )в регистр A.

  2. -A вpre:Увеличение значения A. Копирование A в B.
    -B вpost:Копировать A в B. Увеличить B.

  3. Сохранить регистр B в ячейке памяти переменной. Это означает, что в ++xxдолжно быть lvalue.

  4. Продолжить дополнительные вычисления с результатом в регистре А.

Таким образом, :a ++может применяться только к переменным (, так как их значение должно храниться в памяти по их указателю ), а то, что происходит с переменной (, увеличивается ). ] не зависит от того, что происходит с вычисляемым выражением.

Когда применяется !, результатом является не переменная, а промежуточное значение выражения. Значение выражения не имеет позиции в памяти, в которой оно сохраняется (, пока оно не будет присвоено переменной ). Невозможно применить оператор ++приращения (или декремента--)к результату !(expression).

Теперь должно быть ясно, что единственный способ применения ++— это переменная, называемая x, varилиa[$0](Alvalue). И что !должно быть применено позже к значению в регистреA(текущее значение оцениваемого выражения ).Способ, которым эти факты могут быть выражены, состоит в том, что ++имеет более высокий приоритет над (почти )всем остальным.

Обратите внимание, что единственный другой оператор в спецификации POSIX для awk-приоритета , скобка(expr)(), на самом деле не может использоваться с ++.

$ awk 'BEGIN{ print (2+3)++ }'
awk: cmd. line:1: BEGIN{ print (2+3)++ }
awk: cmd. line:1:                      ^ syntax error

Итак, ++должно быть выше !.

Противники

Для случайных минусовщиков, без какой-либо причины, вы также должны посмотреть это:https://unix.stackexchange.com/a/597931/232326

-2
18.03.2021, 23:21

Теги

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