Как я могу получить длину каждой выходной строки grep
Я очень новичок в bash scripting.
У меня есть файл трассировки сети, который я хочу разобрать. Часть файла трассировки (два пакета):
[continues...]
+---------+---------------+----------+
05:00:00,727,744 ETHER
|0
|00|03|a0|09|5c|1c|00|10|07|df|a4|20|08|00|45|00|00|38|e7|55|
+---------+---------------+----------+
05:00:00,727,751 ETHER
|0
|00|03|a0|09|5c|1c|00|10|07|df|a4|20|08|00|45|00|00|38|e7|56|00|00|3a|01|
[continues...]
Для каждого пакета я хочу напечатать метку времени и длину пакета (шестнадцатеричные значения, идущие в следующей строке после заголовка |0), чтобы выходные данные выглядели следующим образом:
05:00:00.727744 20 bytes
05:00:00.727751 24 bytes
Я могу получить строку с отметкой времени и пакеты отдельно, используя grep в bash:
times=$(grep '..:..:' $fileName)
packets=$(grep '..|..|' $fileName)
Но я не могу работать с отдельными выходными линиями после этого. Целое результат объединяется в две переменные "times"и " packets". Как я могу получить длину каждого пакета?
P.S. была бы признательна хорошая ссылка, которая действительно объясняет, как делать Программирование bash, а не просто делать примеры.
2 ответов:
Вы действительно не хотите делать такие вещи со своей оболочкой.
Вы хотите написать настоящий парсер, который понимает формат вывода необходимой информации.
Для быстрого и грязного взлома вы можете сделать что-то вроде этого:
perl -wne 'print "$& " if /^\d\S*/; print split(/\|/)-2, " bytes\n" if /^\|..\|/'
Хорошо, с простой старой оболочкой...
Вы можете получить длину строки следующим образом:
В этой строке шестьдесят два символа. Думайте о каждом символе как оline="|00|03|a0|09|5c|1c|00|10|07|df|a4|20|08|00|45|00|00|38|e7|55|" wc -c<<<$line 62|00, где00может быть любая цифра. В этом случае на конце есть дополнительный|. Кроме того,wc -cвключает в себяNLна конце. Итак, если мы возьмем значениеwc -cи вычтем 2, то получим60. Если мы разделим это на 3, то получим20, которое является числом символов.Хорошо, теперь нам нужна небольшая петля, вычислить различные линии, а затем разобрать их:
#! /bin/bash while read line do if [[ $line =~ ^[[:digit:]]{2} ]] then echo -n "${line% *}" elif [[ $line =~ ^\|[[:digit:]]{2} ]] then length=$(wc -c<<<$line) ((length-=2)) ((length=length/3)) echo "$length bytes" fi done < test.txtТам a чистый Баш решение ваших проблем!
Вы начинающий программист Bash, и вы понятия не имеете, что происходит... Давайте сделаем это шаг за шагом:Обычным способом перебора файлов в BASH является использование цикла
while read. Это объединяетwhileсread:while read line do echo "My line is '$line'" done < test.txtКаждая строка в
test.txtчитается в$lineпеременная оболочки.Давайте возьмем следующий:
if [[ $line =~ ^[[:digit:]]{2} ]]Это утверждение
if. Всегда используйте скобки[[ ... ]], потому что они исправляют проблемы с интерполяцией оболочки. Кроме того, у них есть немного больше энергии.
=~- это соответствие регулярному выражению.[[:digit:]]соответствует любой цифре.^привязывает регулярное выражение к началу строки, и{2}означает, что я хочу ровно два из них. Это говорит, что если я соответствую строке, которая начинается с двух цифр (что является ваша строка метки времени), выполните это предложениеif.
${line% *}является шаблонным фильтром.%говорит, чтобы соответствовать (glob) наименьшему шаблону glob справа и фильтровать его от моей переменной$line. Я использую это, чтобы удалитьETHERиз моей строки.-nговоритechoне делать NL.Давайте возьмем мой
elif, который является предложением else if.elif [[ $line =~ ^\|[[:digit:]]{2} ]]Опять же, я сопоставляю регулярное выражение. Это регулярное выражение начинается с (
^) a|. Я должен поставить обратную косую черту спереди, потому что|является магическим символом регулярного выражения и\убивает магию. Теперь это просто труба. Затем следуют две цифры. Обратите внимание, что это пропускает|0, но ловит|00.Теперь нам нужно сделать некоторые вычисления:
length=$(wc -c<<<$line)
$(...)говорят, чтобы выполнить вложенную команду и восстановить ее обратно в строку.wc -cсчитает символы, а<<<$line- это то, что мы считаем. Это дало нам62символы. Мы должны вычесть 2, а затем разделить на 3. Это следующие две строки:((length-=2)) ((length/=3))
((...))позволяет мне делать математику на основе целых чисел. Первый вычитает 2 из$length, а следующий делит его на3. Теперь я могу повторить это:И это наш чистый Баш ответ на этот вопрос.echo "$length bytes"
Comments