Grep строка с номером больше 45 - PullRequest
0 голосов
/ 07 августа 2020

У меня есть несколько файлов в каталоге. Я хочу извлечь каждую строку во всех файлах, содержащих целочисленное значение больше 45.

В настоящее время я использую:

grep "IO resumed after" *

Он отображает мне все файлы, которые эта строка " Операция ввода-вывода возобновлена ​​после того, как «Я хочу добавить еще один параметр, который будет отображать все строки» Операция ввода-вывода возобновлена ​​через [число> 45] секунд »

Ответы [ 3 ]

5 голосов
/ 07 августа 2020

Для этого лучше использовать awk:

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

Это ищет строку «IO возобновлено после», если эта строка будет найдена, она возьмет все после этой строки и преобразует ее в число: если подстрока после «IO возобновлено после» начинается с числа, то она будет преобразована в это число, когда мы просто добавим к нему ноль.

Это будет работать, только если строка выглядит так:

xxxxIO resumed after_nnnnyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy

, где x и y - случайные символы, подчеркивание - это любая последовательность пробелов, n - это di git.

Вы можете проверить это с помощью следующих набор команд:

$ seq 40 0.5 50 | awk '{print "foo IO resumed after",$0,"random stuff"}' \
  | awk 'match($0,"IO resumed after") { if (substr($0,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
0 голосов
/ 07 августа 2020

Похоже, мне нужно выучить 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" *)
0 голосов
/ 07 августа 2020

Вы можете использовать альтернативы и количество повторов, чтобы определить шаблон поиска для чисел больше 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

Если числа (can) имеют десятичную точку, трудно определить шаблон для чисел > 45, например, 45.1. Этот шаблон допускает использование десятичной точки или запятой, за которыми следуют цифры, и реализует условие > = 46.

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

2-е изменение:

Шаблоны выше не обрабатывают возможные ведущие нули. Как было предложено пользователем kvantour в комментарии, шаблон может быть расширен, чтобы справиться с этим. Кроме того, если не требуется проверять часть seconds, шаблон для десятичных знаков можно не указывать.

Шаблон для чисел> = 45 с необязательными ведущими нулями:

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