在AWK中使用IF语句

在AWK中使用IF语句

我正在写一个大脚本,我一直在这部分,如果有人可以帮助我

这是文件样本

31:49.9,9.92,TCP ,1_19,490,EXT_SERVER,22,5,257,1,.ASF,0,normal

这是我脚本的一部分

read -p "Please input the function itself ex, > : " function
read -p "Please input the value: " value

如果我这样使用,对我来说工作得很好

cat temp | awk -F',' -v val="$value" '{if($8 > val) print $0}' > $destfile

但是当我尝试这样使用时

cat temp | awk -F',' -v val="$value" -v fn="$function" '{if($8 fn val) print $0}' > $destfile

谢谢

答案1

没有多少编程语言允许在运行时根据变量的内容生成运算符。解析代码时,if 语句的条件中的表达式必须在语法上有效,但事实并非如此。$number variable variable

(当然,在 shell 和test/中[,您可以执行 eg [ "$a" "$op" "$b" ],但那是因为[是一个命令,并在 shell 扩展变量后解析其参数。)

你有一些选择。

您可以让 shell 在 awk 解析代码之前展开运算符,如下所示:

cat temp | awk -F',' -v val="$value" '
               {if($8 '"$function"' val) print $0}' > $destfile

那么如果$function包含eg <,awk会看到{if($8 < val) ...。如果这样做,您应该$function在运行 awk 之前验证它是可接受的运算符。否则,您的用户可能会遇到令人惊讶的语法错误,甚至更糟。


作为另一种选择,您可以让用户输入下限和上限,并始终在代码中检查两者。如果用户不想分别输入下限/上限,则替换例如-inf/或一些其他足够低/高的值。+inf

read -p "Please enter lower limit: " lo
read -p "Please enter upper limit: " hi
cat temp | awk -F',' -v lo="${lo:--inf}" -v hi="${hi:-+inf}" '
               {if (lo <= $8 && $8 <= hi) print $0}' > $destfile

-inf/+inf似乎直接在 GNU awk 和 Busybox 中工作,mawk 似乎需要强制它们使用等数字lo + 0 <= $8。)


我想在 GNU awk 中,第三种选择是为您想要提供的所有不同比较运算符创建函数,然后使用间接函数调用根据变量中给出的名称调用其中之一。

例如,对于小于和大于测试:

read -p "Please input the function (lt or gt): " op
read -p "Please input the value: " value
cat temp | gawk -F',' -v op="$op" -v val="$value" '
                function lt(a, b) { return a < b; }
                function gt(a, b) { return a > b; }
                {if (@op($8, val)) print $0}'

当然,这样做的缺点是您必须显式创建全部函数,如果用户输入无效的函数名称,则会出现错误。

答案2

1.修改awk脚本sed

您可以将 awk 脚本存储在变量中,并在 awk 执行之前使用 sed 对其进行修改。例如

#!/bin/bash

awkscript='COL FN VAL'

col=8
fn='>'
val=2 

awk -f <(printf "%s" "$awkscript" |
           sed -e "s/COL/\$$col/; s/FN/$fn/; s/VAL/$val/") temp

这会将“$awkscript”从 转换COL FN VAL$8 > 2.

简而言之,“awk 脚本”是一个模板,其中一些硬编码字符串(COLFNVAL)被变量替换。

警告:如果任何变量包含 /影响sed脚本解释方式的值(例如 ),则这可能会中断sed。有更安全、更好、更复杂的方法来进行模板化,但是如果您可以确保变量只保存兼容的、不破坏 sed 的值,那么像这样的简单模板就可以了。

您还可以使用文件或特雷多克保存 awk 脚本。

或者,对于一个非常简单的实现,类似:

awk -f <(echo "$col $fn $val") temp

或者

awk -f <(cat <<< "$col $fn $val") temp

2. 使用perleval

您可以perl使用该函数而不是 awk来完成此eval操作。

perl -F, -slne 'print if (eval "$F[7] $fn $val")' -- -val="$value" -fn='>' temp

甚至:

perl -F, -slne 'print if (eval "$F[$col-1] $fn $val")'  -- \
  -col=8 -val="$value" -fn='<' temp

请注意,perl 的数组从零开始,因此它使用$F[7]$8 而不是与 一起使用awk

perl 的-s选项开启了 perl 类似 awk 的能力,可以从命令行进行变量赋值。

man perlrun

-s在程序名称之后、任何文件名参数之前(或 的参数之前--)启用命令行上开关的基本开关解析。在那里找到的任何开关都将从@ARGVPerl 程序中删除并设置相应的变量。如果使用 -xyz 开关调用以下程序,则打印“1”;如果使用 -xyz=abc 调用该程序,则打印“abc”。

   #!/usr/bin/perl -s
   if ($xyz) { print "$xyz\n" }

警告: eval存在潜在危险。除非您严格控制允许提供的内容$fn,否则用户可以导致您的脚本运行任何Perl 代码。

这将是很多更安全的是允许用户仅从有限的预定义运算符集中进行选择。

相关内容