使用shell脚本在范围内检查另一个文件中的编号

时间:2015-03-31 01:59:07

标签: shell unix awk sed grep

我有两个文件(fileA和fileB)。 FileA包含数字列表,fileB包含数字范围。

的fileA

  446646452
  000000001
  63495980020

fileB(range_from和range_to)

  22400208, 22400208
  446646450,    446646450
  63495980000,  63495989999

输出必须

  63495980020

在sql脚本中就像

一样
 select *
 from fileB
 where 446646452 between Range_from and Range_To

如何使用shell脚本执行此操作?

3 个答案:

答案 0 :(得分:2)

打印与任何范围相匹配的数字

$ awk 'FNR==NR{low[NR]=$1+0; hi[NR]=$2+0;next} {for (i in low)if ($1>low[i] && $1<hi[i]){print $1;next}}' fileB fileA
63495980020

如何运作

  • FNR==NR{low[NR]=$1+0; hi[NR]=$2+0;next}

    在第一个文件fileB中读取时,保存数组low中范围的低端和数组hi中的高端。

  • for (i in low)if ($1>low[i] && $1<hi[i]){print $1;next}

    在第二个文件fileA中读取时,请检查每个范围的数字。如果它满足任何范围,则打印并跳至next行。

打印与其各自范围相匹配的数字

$ paste fileA fileB | awk '$1>$2+0 && $1<$3+0{print $1}'
63495980020

请注意,仅打印63495980020。 446646452不在22400208和22400208之间,因此省略。

如何运作

实用程序paste组合了以下文件:

$ paste fileA fileB 
  446646452       22400208, 22400208
  000000001       446646450,    446646450
  63495980020     63495980000,  63495989999

第一列是我们感兴趣的数字,而第二列是范围的低值,第三列是高值。我们想打印第一个值$1,如果它在第二个和第三个之间。为了测试它是否大于第二个,我们可能会尝试:

$1>$2

但是,为了确保awk将字段视为数字而不是字符串,我们对其中一个数字执行加法:

$1>$2+0

同样,要测试第一个数字是否小于第三个数字:

$1<$3+0

将这两个测试与打印命令放在一起产生:

$1>$2+0 && $1<$3+0 {print $1}

此测试在之间严格执行。根据您的要求,您可能更愿意:

$1>=$2+0 && $1<=$3+0 {print $1}

答案 1 :(得分:2)

根据OP的说明,fileA中的每个值都应根据fileB中的所有范围进行检查,以查看它是否属于至少一个范围。
假定范围检查的>=<=逻辑(即,包括与范围端点一致的值)。

awk -F', +' '
  # 1st pass (fileB): read the lower and upper range bounds
 FNR==NR { lbs[++count] = $1+0; ubs[count] = $2+0; next }
  # 2nd pass (fileA): check each line against all ranges.
 { 
   for(i=1;i<=count;++i) {
    if ($1+0 >= lbs[i] && $1+0 <= ubs[i]) { print; next }
   }
 }
' fileB fileA
  • awk用于使用单独的传递读取两个文件:
    • FNR==NR适用于fileB的所有行;建立了范围下界(lbs)和上界(ubs)的并行数组;感谢next,对fileB行没有进一步处理。
    • 后续{...}块仅适用于fileA
    • 中的行
    • 根据所有范围检查fileA中的每个值,一旦找到匹配项,就会打印输入行,处理进入下一行。
    • 为确保所有涉及的令牌都被视为数字,我们会添加+0

答案 2 :(得分:1)

旧时尚剧本

sed 's/,[[:space:]]*/ /' fileB \
 | while read LowVal HighVal
    do
      while read ThisLine
       do
         [ ${ThisLine} -ge ${LowVal} ] && [ ${ThisLine} -le ${HighVal} ] && echo "${ThisLine}"
       done < fileA
    done