Во втором awk one liner я просто заменил < на >, и это дало мне синтаксическую ошибку. Разве нам не разрешено использовать > в условных операторах?

~/Desktop $ awk 'BEGIN{print 3<5 ? "Hello":"World"}'
Hello
~/Desktop $ 
~/Desktop $ awk 'BEGIN{print 3>5 ? "hello": "world"}'
awk: cmd. line:1: BEGIN{print 3>5 ? "hello": "world"}
awk: cmd. line:1:                 ^ syntax error
~/Desktop $
~/Desktop $ awk 'BEGIN{print 5<3 ? "Hello":"World"}'
World
~/Desktop $
~/Desktop $
2
ImHere 30 Авг 2021 в 11:00

3 ответа

Оператор print в awk принимает одну из трех форм:

  • print > expression
  • print >> expression
  • print | expression

... где бит >, >> и |, а также следующий за ним expression являются необязательными.

Команда print > expression приведет к тому, что вывод будет направлен в файл, названный любой строкой, которую оценивает expression. Если файл существует, он будет усечен (очищен). Это похоже на то, как работает перенаправление вывода в оболочке, но файл не будет усечен выполнением того же оператора print во второй раз, если только close(expression) не используется для закрытия файла, связанного с expression первый.

Формы >> и | команды print также вдохновлены тем, как оболочка обрабатывает эти маркеры, но дополнительную информацию об этих формах см. в руководстве по awk.

В вашем коде у вас есть

print 3 > 5 ? "Hello" : "World"

Это соответствует синтаксису print > expression и поэтому выводит строку 3 в файл с именем 5. Остальная часть этой строки продолжается знаком вопроса, в котором ваш awk не может найти особого смысла, поэтому он жалуется на это. Некоторые реализации awk будут использовать бит 5 ? "Hello" : "World" в качестве expression и поэтому будут записывать 3 в файл с именем Hello (поскольку 5 является значение true при использовании в качестве логического значения).

То, что вы, скорее всего, хотели сделать, это

print ( 3 > 5 ? "Hello" : "World" )

Или

print ( 3 > 5 ) ? "Hello" : "World"

Это гарантирует, что синтаксис print > expression не будет запущен.

6
Kusalananda 30 Авг 2021 в 12:37
FWIW в GNU awk есть 4-я форма print, которая представляет собой print |& для связи с сопроцессом.
 – 
Ed Morton
30 Авг 2021 в 16:19

Используйте текст только для своих демонстраций.

Используйте круглые скобки вокруг вашего выражения:

$ awk 'BEGIN{print (5>3 ? "Hello":"World")}'
Hello
$ awk 'BEGIN{print (3>5 ? "Hello":"World")}'
World

Возможно, символ > интерпретируется как перенаправление в файл для команды печати

2
Arnaud Valmary 30 Авг 2021 в 08:01
1
Обратите внимание, что с BEGIN{print 3>5 ? "Hello":"World"}, mawk и busybox awk записывают 3 в файл с именем Hello, в то время как некоторым другим требуется BEGIN{print 3>(5 ? "Hello":"World")} для этого.
 – 
Stéphane Chazelas
30 Авг 2021 в 08:34

В вашем коде есть троичное выражение без скобок [возможно] справа от перенаправления вывода. Есть 2 проблемы с этим:

  • Выражение без скобок справа от перенаправления вывода (или ввода) является неопределенным поведением для POSIX, поэтому никогда не делайте этого.
  • Тернарное выражение в скобках труднее читать, чем выражение со скобками, и может привести к синтаксическим ошибкам в некоторых awks в некоторых контекстах, поэтому никогда не делайте этого.

Плохой:

print > foo bar
getline < foo bar
str = x>y ? foo : bar

Хороший:

print > (foo bar)
getline < (foo bar)
str = (x>y ? foo : bar)

Однако при создании нескольких выходных файлов обычно рекомендуется закрывать их по мере продвижения, а затем вы сохраняете имя выходного файла, являющееся результатом выражения, в переменной, и тогда вам не нужны круглые скобки, например:

out = foo bar
print > out
close(out)

Итак, ваш код:

awk 'BEGIN{print 3<5 ? "Hello" : "World"}'
awk 'BEGIN{print 3>5 ? "hello" : "world"}'
awk 'BEGIN{print 5<3 ? "Hello" : "World"}'

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

awk 'BEGIN{print (3<5 ? "Hello" : "World")}'
awk 'BEGIN{print (3>5 ? "hello" : "world")}'
    or, less likely, awk 'BEGIN{print 3 > (5 ? "hello" : "world")}'
awk 'BEGIN{print (5<3 ? "Hello" : "World")}'
1
Ed Morton 30 Авг 2021 в 17:38