URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 7862
[ Назад ]

Исходное сообщение
"разобрать строку на bash"

Отправлено stone , 27-Янв-09 15:55 
Есть файл вида
# IPFMv0.11.5 2009/01/24 03:00:00 (local time) -- dump every 1d00:00:00 -- listening on fxp0
# Host                                  In (bytes)    Out (bytes)  Total (bytes)
relay                                  1173415529      110929187     1284344716
# end of dump 2009/01/24 03:00:00


Все хорошо но нужно чтоб было не в байтах а в кило/мега/гига байтах
залез в сырцы ipfm (data.c)- вроде нашел там структуры с полями in/out, но хз, правильно я там поделю, если б там еще комментарии были хоть какие-нибудь
Есть в инете скрипты на перле, но там куча всего ненужного, мне нужно одну строчку отформатировать и все.Просто в баше не силен, подскажите как


Содержание

Сообщения в этом обсуждении
"разобрать строку на bash"
Отправлено angra , 27-Янв-09 18:39 
И чем перл неугодил? На перле, сохраняя разделители и меняя только цифры:
$ perl -pe 'use integer;$d=1024;$_=$1.($2/$d).$3.($4/$d).$5.($6/$d)."\n" if /^(\S+\s+)(\d+)(\s+)(\d+)(\s+)(\d+)$/;' <<eof
> # IPFMv0.11.5 2009/01/24 03:00:00 (local time) -- dump every 1d00:00:00 -- listening on fxp0
> # Host                                  In (bytes)    Out (bytes)  Total (bytes)
> relay                                  1173415529      110929187     1284344716
> # end of dump 2009/01/24 03:00:00
> eof

# IPFMv0.11.5 2009/01/24 03:00:00 (local time) -- dump every 1d00:00:00 -- listening on fxp0
# Host                                  In (bytes)    Out (bytes)  Total (bytes)
relay                                  1145913      108329     1254242
# end of dump 2009/01/24 03:00:00
Как легко догадаться $d есть делитель, нужны мегабайты поставь $d=1024*1024


"разобрать строку на bash"
Отправлено allez , 27-Янв-09 18:57 
>Есть в инете скрипты на перле, но там куча всего ненужного, мне
>нужно одну строчку отформатировать и все.Просто в баше не силен, подскажите
>как

Вот вам быстренько и грязненько. Очень грязненько :-)
Сразу оговорюсь, что во-первых, этот скрипт "сломается" при обработке чисел больше 1 петабайта,
во-вторых, его можно сделать и компактнее, и красивее, а в-третьих, я этого делать не буду, ибо
мне оно не надо и лениво. :-)


$ cat file
# IPFMv0.11.5 2009/01/24 03:00:00 (local time) -- dump every 1d00:00:00 -- listening on fxp0
# Host                                  In (bytes)    Out (bytes)  Total (bytes)
relay                                  1173415529      110929187     1284344716
# end of dump 2009/01/24 03:00:00

$ cat script.sh
#!/bin/sh

humanize()
{
  var=$1
  unit[1]="Kbytes"
  unit[2]="Mbytes"
  unit[3]="Gbytes"
  unit[4]="Tbytes"
  for ((i=1;i<=4;i++));
  do
    declare -i intvar=$(echo "$var" | awk -F '.' '{print $1}')
    if [ $intvar -lt 1024 ]
    then
      echo "$var ${unit[$i]}"
      break
    else
      var=$(echo "scale=2; $var/1024" | bc -l)
    fi
  done
}

file=$1

cat "$file" | grep "^relay" | \
while read line;
do
  IN=$(echo "$line" | awk '{print $2}')
  OUT=$(echo "$line" | awk '{print $3}')
  TOTAL=$(echo "$line" | awk '{print $4}')

  echo -n "In: "
  humanize $IN

  echo -n "Out: "
  humanize $OUT

  echo -n "Total: "
  humanize $TOTAL
done

$ ./script.sh file
In: 1.09 Tbytes
Out: 105.79 Gbytes
Total: 1.19 Tbytes



"разобрать строку на bash"
Отправлено stone , 28-Янв-09 17:44 
И на том спасибо!
perl я имел ввиду что нашел целую большую прогу для обработки, а мне просто одну строчку менять надо

"разобрать строку на bash"
Отправлено angra , 28-Янв-09 18:00 
Ну так я вроде и дал однострочник на перле меняющий строки по регексу на то, что тебе надо. Если вдруг непонятно как использовать, то подавайте данные на stdin или укажите имя файла, а вывод перенаправляйте куда вам угодно. Альтернативно можно вызвать с ключом -i, тогда будет менять внутри файла, а не выводить на stdout, пример:
perl -i -pe 'use integer;$d=1024;$_=$1.($2/$d).$3.($4/$d).$5.($6/$d)."\n" if /^(\S+\s+)(\d+)(\s+)(\d+)(\s+)(\d+)$/;' somefile

"разобрать строку на bash"
Отправлено Andrey Mitrofanov , 29-Янв-09 12:58 
>мне просто одну строчку менять надо

Вас удивляет, что bash - не совсем подходящий инструмент для?


"разобрать строку на bash"
Отправлено stone , 29-Янв-09 15:13 
>>мне просто одну строчку менять надо
>
>Вас удивляет, что bash - не совсем подходящий инструмент для?

Как я уже сказал, я в баше не силен,поэтому я ничему не удивляюсь)


"разобрать строку на bash"
Отправлено allez , 29-Янв-09 15:48 
>>мне просто одну строчку менять надо
>
>Вас удивляет, что bash - не совсем подходящий инструмент для?

Да вроде бы подходящий:


$ cat file
# IPFMv0.11.5 2009/01/24 03:00:00 (local time) -- dump every 1d00:00:00 -- listening on fxp0
# Host                                  In (bytes)    Out (bytes)  Total (bytes)
relay                                  1173415529      110929187     1284344716
# end of dump 2009/01/24 03:00:00

$ cat file | grep "^relay" | awk '{printf "%10.2f\t", $2/1024; printf "%10.2f\t", $3/1024; printf "%10.2f\n", $4/1024}'
1145913.60       108329.28      1254242.89 # Kbytes

$ cat file | grep "^relay" | awk '{printf "%10.2f\t", $2/(1024*1024); printf "%10.2f\t", $3/(1024*1024); printf "%10.2f\n", $4/(1024*1024)}'
   1119.06          105.79         1224.85 # Mbytes


Я, видимо, недостаточно внимательно прочел сообщение автора темы и решил, что ему требуется
привести данные в human-readable вид.

P. S. К слову, в скрипте я допустил ошибку и он на порядок завышает единицу измерения - вместо
мегабайт пишет гигабайты и т. д. Функция humanize() должна выглядеть следущим образом:


humanize()
{
  var=$1
  unit[1]="Bytes"
  unit[2]="Kbytes"
  unit[3]="Mbytes"
  unit[4]="Gbytes"
  unit[5]="Tbytes"
  for ((i=1;i<=5;i++));
  do
    declare -i intvar=$(echo "$var" | awk -F '.' '{print $1}')
    if [ $intvar -lt 1024 ]
    then
      echo "$var ${unit[$i]}"
      break
    else
      var=$(echo "scale=2; $var/1024" | bc -l)
    fi
  done
}


"на bash------"
Отправлено Andrey Mitrofanov , 29-Янв-09 18:23 
>>>мне просто одну строчку менять надо
>>Вас удивляет, что bash - не совсем подходящий инструмент для?

"Удивляет" - было к "я просто хотел на баше[, а вы мне тут скриптовых языков]".

>Да вроде бы подходящий:
>$ cat file | grep "^relay" | awk '{printf ".2f\t", $2/1024; printf

Под башем _я_ имел в виду баш. Как бы это ни было удивительно. Не "юниховый шелл скриптинг" вообще. Строку-таки у Вас меняет awk, не /bin/bash. На шелле можно было бы числа подставлять-переписывать-пересчитавыть... даже наверное без grep-ов-awk-ов, только это никому в голову не пришло -- все взяли "более подходящий инструмент".


"на bash------"
Отправлено allez , 30-Янв-09 07:37 
>Под башем _я_ имел в виду баш. Как бы это ни было
>удивительно. Не "юниховый шелл скриптинг" вообще. Строку-таки у Вас меняет awk,
>не /bin/bash.

Да уж, действительно удивили. :-)
Первоочередная задача shell - интерпретировать и выполнять команды, в том числе и команды
запуска внешних программ. Вот и запускает он у меня awk, который предназначен для работы с
текстом. Все же, как мне представляется, если человек пишет, что "в баше не
силен", то в виду имеется как раз "юниховый шелл скриптинг" а не "чистый shell".


>На шелле можно было бы числа подставлять-переписывать-пересчитавыть... даже наверное
>без grep-ов-awk-ов, только это никому в голову не пришло -- все
>взяли "более подходящий инструмент".

И это, на мой взгляд, вполне естественно. Действительно, можно было бы обойтись без grep и awk,
но трудозатраты при этом были бы совершенно неоправданными. По крайней мере, для меня. :-)


"на bash------"
Отправлено angra , 30-Янв-09 13:50 
Ну тогда вспомним, что perl в шелл скриптах такой же равноправный елемент как и awk/sed/grep итд, только значительно изящней, эффективней и надежней. Так что большинство заданий "написать шелл скрипт" можно свести к вызову перлового однострочника. Однако иногда для проверки сисадмина на знание шелла и способность программировать дают задание написать на чистом шелле, без вызова внешних программ, так что не стоит подобному удивляться.

"разобрать строку на bash"
Отправлено phpcoder , 29-Янв-09 20:16 
>$ cat file | grep "^relay" | awk '{printf "%10.2f\t", $2/1024; printf
>"%10.2f\t", $3/1024; printf "%10.2f\n", $4/1024}'

Можно ведь и покороче:

awk '{if($0~/^relay/){printf("%10.2f\t%10.2f\t%10.2f\n", $2/1024, $3/1024, $4/1024)}}' file


"разобрать строку на bash"
Отправлено allez , 30-Янв-09 07:59 
>>$ cat file | grep "^relay" | awk '{printf "%10.2f\t", $2/1024; printf
>>"%10.2f\t", $3/1024; printf "%10.2f\n", $4/1024}'
>
>Можно ведь и покороче:
>
>awk '{if($0~/^relay/){printf("%10.2f\t%10.2f\t%10.2f\n", $2/1024, $3/1024, $4/1024)}}' file

Разумеется, можно. :-)


"разобрать строку на bash"
Отправлено stone , 01-Фев-09 12:04 
Еще раз всем спасибо за горячий спор и работающие скрипты)