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