【问题标题】:awk operator in a variable变量中的 awk 运算符
【发布时间】:2021-02-18 05:22:43
【问题描述】:

我有 2 个文件

cat file1.txt
lspol > 8296
....
cat file2.txt
lspol 8297
...

如果 file2.txt 中第 1 列的数字大于 file1.txt 中第 1 列的数字,我正在尝试获取输出

下面的命令很好用

# if column 1 of file1.txt is equal to column 1 of file2.txt and column 3 of file1.txt is greater than column 2 in file2.txt
awk '
   {
       getline buf <f2;
       split( buf, a, " " );
       if( $1 == a[1]  && $3+0 > a[2]+0 )
           printf( "%s\n", buf );
   }
' f2="file2.txt" file1.txt

我试图从 file1.txt 的第二列中提取运算符,但没有运气。我尝试了很多方法,这里是其中之一

awk '
   {
       getline buf <f2;
       split( buf, a, " " );
       if( $1 == a[1]  && $3+0 $2 a[2]+0 )
           printf( "%s\n", buf );
   }
' f2="file2.txt" file1.txt

【问题讨论】:

  • 这是一个不愉快的混合代码和数据的尝试。你可以全力以赴,让 shell 从你从数据中挑选出来的字符串编写一个 Awk 脚本,或者做安全但乏味的事情,将每个操作数字符串映射到一个函数,比如 if((oper=="&lt;") &amp;&amp; (a &lt; b)) ... else if ((oper=="&gt;") &amp;&amp; (a &gt; b)) ...

标签: linux bash awk


【解决方案1】:

你可以构建这样的东西......

$ awk 'NR==FNR{cond[$1]=$2; v[$1]=$3; next}
              {switch(cond[$1])  {
                 case "<": if($2<v[$1]) print; break;
                 case ">": if($2>v[$1]) print; break;
                 case "=": if($2==v[$1]) print; break;
                 default: print "unknown op or missing " $1; break;
              }}' file1 file2

lspol 8297

【讨论】:

  • 你应该提到switch()需要GNU awk。
【解决方案2】:

使用未经验证的输入总是有风险的,但我认为这可能是你想要做的:

$ cat tst.awk
NR==FNR {
    ops[$1] = $2
    vals[$1] = $3
    next
}
{ comparison = sprintf("%d %s %d", $2, ops[$1], vals[$1]) }
system("awk \047BEGIN{exit} END{exit (" comparison ")}\047")

$ awk -f tst.awk file1 file2
lspol 8297

每行末尾的数值已经是安全的,因为如果它们不是数字,它们会被专门转换为数字,您可以通过以下方式使操作符安全:

$ cat tst.awk
NR==FNR {
    if ( $2 ~ /^[!<>=~]{1,2}$/ ) {
        ops[$1]  = $2
        vals[$1] = $3
    }
    else {
        print "Bad operator:", $2 | "cat>&2"
        exit 1
    }
    next
}
{ comparison = sprintf("%d %s %d", $2, ops[$1], vals[$1]) }
system("awk \047BEGIN{exit} END{exit (" comparison ")}\047")

或其他一些这样的正则表达式,用于您想要支持的任何比较运算符。

上述作弊,因为它没有在 1 个 awk 命令内评估运算符,而是使用 awk 通过子 shell 调用 awk 来评估您要测试的表达式。鉴于此,它将比在 1 个 awk 命令中硬编码比较慢几个数量级。

另请参阅https://stackoverflow.com/a/54161251/1745001 以获得类似的脚本。

如果这不是您想要做的,那么编辑您的问题以阐明您的要求并提供更具代表性的示例输入/输出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-17
    • 1970-01-01
    • 2011-10-11
    • 1970-01-01
    • 2014-02-03
    • 1970-01-01
    相关资源
    最近更新 更多