Grep 一个数字大于 45 的字符串

Grep a string with number greater than 45

我在一个目录中有多个文件。我想提取所有包含整数值大于 45 的文件中的每一行。

目前,我正在使用:

grep "IO resumed after" *

它向我显示了这个字符串“IO resumed after”的所有文件 我想再添加一个参数,它将 grep 所有行“IO 在 [number >45] 秒后恢复”

这个最好用awk:

awk 'match([=10=],"IO resumed after") { if (substr([=10=],RSTART+RLENGTH)+0 > 45) print }' file

这将搜索字符串“IO resumed after”,如果找到该字符串,它将获取该字符串之后的所有内容并将其转换为数字:如果“IO resumed after”之后的子字符串以数字开头,则当我们向它加零时它会被转换成那个数字。

这仅在行如下所示时有效:

xxxxIO resumed after_nnnnyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy

其中xy是随机字符,下划线是任意空格序列,n是数字。

您可以使用以下一组命令对其进行测试:

$ seq 40 0.5 50 | awk '{print "foo IO resumed after",[=12=],"random stuff"}' \
  | awk 'match([=12=],"IO resumed after") { if (substr([=12=],RSTART+RLENGTH)+0 > 45) print }'

输出:

foo IO resumed after 45.5 random stuff
foo IO resumed after 46.0 random stuff
foo IO resumed after 46.5 random stuff
foo IO resumed after 47.0 random stuff
foo IO resumed after 47.5 random stuff
foo IO resumed after 48.0 random stuff
foo IO resumed after 48.5 random stuff
foo IO resumed after 49.0 random stuff
foo IO resumed after 49.5 random stuff
foo IO resumed after 50.0 random stuff

您可以使用替代项和重复计数来定义大于 45 的数字的搜索模式。

此解决方案假定数字是不带小数点的整数。

grep 'IO resumed after \(4[6-9]\|[5-9][0-9]\|[0-9]\{3,\}\) seconds'

或更短 egrep:

egrep 'IO resumed after (4[6-9]|[5-9][0-9]|[0-9]{3,}) seconds'

我用

测试了模式
for i in 1 10 30 44 45 46 47 48 49 50 51 60 99 100 1234567
do
echo "foo IO resumed after $i seconds bar"
done | grep 'IO resumed after \(4[6-9]\|[5-9][0-9]\|[0-9]\{3,\}\) seconds'

打印

foo IO resumed after 46 seconds bar
foo IO resumed after 47 seconds bar
foo IO resumed after 48 seconds bar
foo IO resumed after 49 seconds bar
foo IO resumed after 50 seconds bar
foo IO resumed after 51 seconds bar
foo IO resumed after 60 seconds bar
foo IO resumed after 99 seconds bar
foo IO resumed after 100 seconds bar
foo IO resumed after 1234567 seconds bar

如果数字(可以)有小数点,则很难定义数字 > 45 的模式,例如45.1.
此模式允许小数点或逗号后跟数字并实现条件 >= 46.

grep 'IO resumed after \(4[6-9]\|[5-9][0-9]\|[0-9]\{3,\}\)\([.,][0-9]*\)\{,1\} seconds'

第二次编辑:

以上模式不处理可能的前导零。正如用户 kvantour 在评论中所建议的那样,可以扩展模式来处理这个问题。此外,如果不需要检查seconds部分,小数点的模式可以省略。

数字的模式 >= 45,可选前导零:

grep 'IO resumed after 0*\(4[5-9]\|[5-9][0-9]\|[1-9][0-9]\{2,\}\)'

看来我需要学习 awk 直到我找到 bash 解决方案。如果没有小数点的秒数则为:

while read line; do
    number=${line//*after}
    number=${number//seconds*}
    ((number>45)) && echo $line
done <<< $(grep "IO resumed after" *)

否则我们必须使用bc:

while read line; do
    number=${line//*after}
    number=${number//seconds*}
    case $(bc <<< "$number>45") in 1) echo "$line";; esac
done <<< $(grep "IO resumed after" *)