Переменный оператор для численного сравнения в awk - PullRequest
0 голосов
/ 30 января 2019

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

awk -v o="$operator" -v c="$comparison" '$1 o c'

Ответы [ 3 ]

0 голосов
/ 30 января 2019

Другим способом, предложенным Kaz , было бы определение собственной функции отображения, которая принимает в качестве аргумента две переменные и соответствующую строку оператора o:

awk -v o="$operator" -v c="$comparison" '
      function operator(arg1, arg2, op) {
          if (op == "==") return arg1 == arg2
          if (op == "!=") return arg1 != arg2
          if (op == "<") return arg1 < arg2 
          if (op == ">") return arg1 > arg2
          if (op == "<=") return arg1 <= arg2 
          if (op == ">=") return arg1 >= arg2 
      }
    { print operator($1,c,o) }'

Таким образом, вы также можете определить свои собственные операторы.

0 голосов
/ 30 января 2019

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

$ operator='>'; comparison='3'
$ echo 5 | awk -v c="$comparison" '$1 '"$operator"' c'
5

В противном случае вы можете написатьваша собственная функция eval-стиля, например:

$ cat tst.awk
cmp($1,o,c)

function cmp(x,y,z,      cmd,line,ret) {
    cmd = "awk \047BEGIN{print (" x " " y " " z ")}\047"
    if ( (cmd | getline line) > 0 ) {
        ret = line
    }
    close(cmd)
    return ret
}

$ echo 5 | awk -v c="$comparison" -v o="$operator" -f tst.awk
5

См. https://stackoverflow.com/a/54161251/1745001. Последняя будет работать, даже если ваша awk-программа была сохранена в файле, а первая - нет.Если вы хотите смешать библиотеку функций со скриптами командной строки, то вот один способ с GNU awk для -i:

$ cat tst.awk
function cmp(x,y,z,      cmd,line,ret) {
    cmd = "awk \047BEGIN{print (" x " " y " " z ")}\047"
    if ( (cmd | getline line) > 0 ) {
        ret = line
    }
    close(cmd)
    return ret
}

$ awk -v c="$comparison" -v o="$operator" -i tst.awk 'cmp($1,o,c)'
5
0 голосов
/ 30 января 2019

Нет, это не может работать.Опция -v в Awk определяет действительные переменные Awk, а не подстановки макросов на уровне токена.

Не работает по той же причине, по которой это не работает:

awk 'BEGIN { o = "+"; print 2 o 2 }'  # hoping for 2 + 2

Awkотличается от оболочки POSIX и аналогичных языков;он не оценивает переменные с помощью текстовой подстановки.

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

awk -v c="$comparison" "\$1 $operator c"

Теперь нам нужен обратный слеш на $1, потому что мы переключились на двойные кавычки, внутри которых $1 теперь распознается самой оболочкой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...