使用 awk 检查一个变量中特定列中每一行的数字与另一个变量中两个特定列中的所有行

使用 awk 检查一个变量中特定列中每一行的数字与另一个变量中两个特定列中的所有行

我需要使用 来检查一个变量中特定列中每一行中的数字与另一个变量中两个特定列中的所有行awk,并将行保留在第一个符合参数的变量中。

到目前为止,我曾尝试通过一个强大的awk命令来做到这一点,但都失败了。显然,我可以在外部循环中执行此操作,但它会非常慢,因为我有数百行或数千行要检查。我感谢解决这个问题的所有帮助,并且我一直在寻求改进 awk 的使用,所以如果您有解决方案,最好有一个解释,以便我可以学习和提高自己。

这是一个例子:

  • 假设我只想打印第 2 列中的行${ListToCheckFrom},如果任意行中的数字 > 第 2 列和 < 第 3 列${ListToCheckAgainst}

  • 输入示例:

    ListToCheckFrom="C,2  
    C,22  
    C,12  
    hr,15"
    
    ListToCheckAgainst="C1,25,50  
    hr1,22,30  
    r,12,18  
    C,15,44"  
    
  • 预期输出:

    C,22  
    hr,15
    

答案1

由于您已经用 标记了问题bash,因此您可以利用进程替换来读取 shell 变量,例如输入文件。以下脚本片段应该执行以下操作:

#!/bin/bash

ListToCheckFrom="C,2  
C,22  
C,12  
hr,15"

ListToCheckAgainst="C1,25,50  
hr1,22,30  
r,12,18  
C,15,44"

awk -F',' 'list=="constr"{n++; low[n]=$2;high[n]=$3;next}
           {for (i=1;i<=n;i++) {if ($2>low[i]&&$2<high[i]) {print;next};}}' \
           list=constr <(echo "$ListToCheckAgainst") \
           list=chk <(echo "$ListToCheckFrom")

这将指定第一个输入文件echo的内容和第二个输入文件的内容。它将在“打开”每个文件之前或之前设置一个变量,以便可以在内部区分当前正在处理哪个“文件”。$ListToCheckAgainstecho$ListToCheckFromawklistconstrchkawk

  • 处理 中的“约束”时$ListToCheckAgainst,它只是将第 2 列和第 3 列中指定的“下限”和“上限”分别存储在数组lowhigh中。除此之外,它会立即跳过处理到下一个输入行。
  • 当处理要检查的列表时$ListToCheckFrom,它会扫描之前注册的所有范围,如果发现第 2 列属于其中任何一个范围,则打印它(并立即跳过处理到下一个输入行)。

如果您的数据存储在“物理”文件中而不是 shell 变量中,则可以简单地使用文件名而不是进程替换作为命令行参数。

答案2

$ cat tst.sh
#!/usr/bin/env bash

ListToCheckFrom='C,2
C,22
C,12
hr,15'

ListToCheckAgainst='C1,25,50
hr1,22,30
r,12,18
C,15,44'

awk '
    BEGIN { FS="," }
    NR==FNR {
        begs2ends[$2] = $3
        next
    }
    {
        for ( beg in begs2ends ) {
            beg += 0
            end = begs2ends[beg]+0
            if ( (beg < $2) && ($2 < end) ) {
                print
                next
            }
        }
    }
' <(printf '%s\n' "$ListToCheckAgainst") <(printf '%s\n' "$ListToCheckFrom")

$ ./tst.sh
C,22
hr,15

相关内容