awk中数值比较的变量算子

awk中数值比较的变量算子,awk,Awk,awk可以使用变量运算符进行数值比较吗?以下代码适用于硬编码运算符,但不适用于变量运算符: awk -v o="$operator" -v c="$comparison" '$1 o c' 不,那不行。Awk的-v选项定义实际的Awk变量,而不是令牌级宏替换 它不起作用的原因与它不起作用的原因相同: awk 'BEGIN { o = "+"; print 2 o 2 }' # hoping for 2 + 2 Awk不同于POSIX shell和类似的语言;它不通过文本替换来计算变量 由于

awk可以使用变量运算符进行数值比较吗?以下代码适用于硬编码运算符,但不适用于变量运算符:

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

不,那不行。Awk的
-v
选项定义实际的Awk变量,而不是令牌级宏替换

它不起作用的原因与它不起作用的原因相同:

awk 'BEGIN { o = "+"; print 2 o 2 }'  # hoping for 2 + 2
Awk不同于POSIX shell和类似的语言;它不通过文本替换来计算变量

由于您是从shell命令行调用Awk,因此可以使用shell的替换来生成Awk语法,从而获得以下效果:

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

我们现在需要在
$1
上使用反斜杠,因为我们切换到了双引号,其中
$1
现在由shell本身识别。

另一种方法是定义自己的映射函数,该函数将两个变量作为参数和相应的运算符字符串
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) }'
awk-vo=“$operator”-vc=“$comparison””
函数运算符(arg1、arg2、op){
if(op==“==”)返回arg1==arg2
如果(op==“!=”)返回arg1!=arg2
如果(op==“”)返回arg1>arg2
如果(op==“=”)返回arg1>=arg2
}
{打印操作员($1,c,o)}'

通过这种方式,您还可以定义自己的运算符。

否,但您有两个选项,最简单的是让shell在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
看。即使您的awk程序保存在一个文件中,后者也能工作,而前者不能。如果您想将函数库与命令行脚本混合使用,那么对于
-i
,这里有一种使用GNU awk的方法:

$ 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

此时也不需要变量,也可以在引号中移动它。@karakfa如果不知道
比较的确切内容,我们就不能进行该调用。考虑<代码> AWK-V C=A“B”开始{CultC} <代码>。如果我们将代码< >“B<代码> >到AWK脚本的主体中来代替<代码> c>代码>,即使我们把它放在引号中,也会产生语法错误。另一方面,根据设计,
$operator
可能是有效的Awk运算符令牌。
-v
机制的存在是有原因的;它比在Awk语法中插入文本更健壮。