将 AWK FNR 保存为 Bash 变量以继续从该行开始搜索

将 AWK FNR 保存为 Bash 变量以继续从该行开始搜索

我正在尝试在已排序的文件上运行它。这将返回与前 9 个字符相比小于或等于给定值的最后一行。

这将执行多次,并且VALUE将在每次运行时分配,并且我必须从找到我之前的解决方案之后的行继续搜索。我知道FNR给了我当前的行号,但无法将其保存为 BASH 变量以进行操作。

我的file看起来像这样:

093051721DABCD
093052654EEFGH
093053087TIJKL

$ VALUE=093052054;
$ cat file | awk '{if((substr($0,0,9) <= $VALUE)){print $0} else exit}' | tail -1
093051721DABCD

还有其他方法可以做到这一点吗?

答案1

VALUE=083551726
awk -v CMPVALUE="$VALUE" '{linevalue=substr($0,0,9)+0; CMPVALUE=CMPVALUE+0;
  if(linevalue > CMPVALUE) exit; lineno=FNR};
  END {if (lineno>0) print lineno " " $0;
  else print "0 ";}' file
0 

VALUE=083551726555
awk -v CMPVALUE="$VALUE" '{linevalue=substr($0,0,9)+0; CMPVALUE=CMPVALUE+0;
  if(linevalue > CMPVALUE) exit; lineno=FNR};
  END {if (lineno>0) print lineno " " $0;
  else print "0 ";}' file
3 093053087TIJKL

答案2

考虑这个bash版本:

#! /bin/bash
exec 3<test.txt
COUNT=0
while read VALUE
do
    if [[ -z $LAST_VAL ]]
    then
        IN_VAL="$LAST_VAL"
    else
        LINE="$(head <&3 -1)"
        IN_VAL="$(cut -c1-9 <<<'$LINE')"
        let COUNT=$COUNT+1
    fi

    while [[ $IN_VAL < $VALUE ]]
    do
        LINE="$(head <&3 -1)"
        IN_VAL="$(cut -c1-9 <<<'$LINE')"
        let COUNT=$COUNT+1
        LAST_VAL="$IN_VAL"
        [[ -z $IN_VAL ]] && break
    done
    echo $((COUNT - 1)) $LINE
    [[ -z $IN_VAL ]] && break
done

head(以及其他一些工具,例如grepwith --max-count),与 不同的是awk,它将流保留在最后一个读取的字符之后,因此您可以在以后继续使用相同的流进行搜索。问题是当读取的值不匹配时,因此您需要将其保存以供下一次迭代使用(正如我在 参考资料中所做的那样LAST_VAL)。COUNT和的值LINE应该是最后匹配的行号和行。这样,整个事情就可以在一次通读文件的过程中完成。

相关内容