我正在写一个大脚本,我一直在这部分,如果有人可以帮助我
这是文件样本
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 脚本”是一个模板,其中一些硬编码字符串(COL
、FN
和VAL
)被变量替换。
警告:如果任何变量包含 /
影响sed
脚本解释方式的值(例如 ),则这可能会中断sed
。有更安全、更好、更复杂的方法来进行模板化,但是如果您可以确保变量只保存兼容的、不破坏 sed 的值,那么像这样的简单模板就可以了。
您还可以使用文件或特雷多克保存 awk 脚本。
或者,对于一个非常简单的实现,类似:
awk -f <(echo "$col $fn $val") temp
或者
awk -f <(cat <<< "$col $fn $val") temp
2. 使用perl
和eval
您可以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在程序名称之后、任何文件名参数之前(或 的参数之前
--
)启用命令行上开关的基本开关解析。在那里找到的任何开关都将从@ARGV
Perl 程序中删除并设置相应的变量。如果使用 -xyz 开关调用以下程序,则打印“1”;如果使用 -xyz=abc 调用该程序,则打印“abc”。#!/usr/bin/perl -s if ($xyz) { print "$xyz\n" }
警告: eval
存在潜在危险。除非您严格控制允许提供的内容$fn
,否则用户可以导致您的脚本运行任何Perl 代码。
这将是很多更安全的是允许用户仅从有限的预定义运算符集中进行选择。