LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - General
User Name
Password
Linux - General This Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.

Notices


Reply
  Search this Thread
Old 10-20-2011, 04:21 PM   #1
Xeratul
Senior Member
 
Registered: Jun 2006
Location: UNIX
Distribution: FreeBSD
Posts: 2,657

Rep: Reputation: 255Reputation: 255Reputation: 255
Awk to convert bytes to human number?


Hello,

I would like to find a program that could convert bytes to something readable mb, gb...

Here a line that is too difficult to read, and to be converted to human size:
received_bytes=1452360394 transmitted_bytes=3135845922

Awk is extremely flexible + very universal. Present almost on any distros.

With google I have not found such a code for awk. Maybe you've got that alreay?

Thank you in advance.
 
Old 10-20-2011, 05:00 PM   #2
anomie
Senior Member
 
Registered: Nov 2004
Location: Texas
Distribution: RHEL, Scientific Linux, Debian, Fedora
Posts: 3,935
Blog Entries: 5

Rep: Reputation: Disabled
Is simple division OK? For instance:
Code:
$ echo '1452360394' | awk '{ foo = $1 / 1024 / 1024 ; print foo "MB" }'
Not very robust, but it's easy to whip out for ad-hoc use.
 
Old 10-21-2011, 01:57 AM   #3
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
Here's a previous thread covering the same subject:

http://www.linuxquestions.org/questi...gb-etc-597921/

Edit: And here's another version I just found here (#13):
Code:
awk '{ split( "KB MB GB" , v ); s=1; while( $1>1024 ){ $1/=1024; s++ } print int($1) v[s] }'
I fixed the "smart quotes" the page was using, and modified it slightly so that the output is in a more standardized format ("25MB", "19GB", etc). You'll have to modify the field it processes for your own output, of course.

Last edited by David the H.; 10-21-2011 at 02:11 AM. Reason: as stated
 
Old 10-21-2011, 04:15 AM   #4
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
I rewrote the above into a script that will process the line given above, with the important part set up as a function at the top.

Code:
#!/usr/bin/awk -f

function readable( input,     v,s )
  {
	split( "KB MB GB TB" , v )
	if( input + 0.0 == input )   #confirms that the input is a number
	   {
		while( input > 1024 ) { input /= 1024 ; s++ }
		return sprintf( "%0.2f %s" , input , v[s] )
	   }
	else
	   {
		return input
	   }
  }

BEGIN{
	FS="[= ]+"
     }

{
	if ( $0 ~ /_bytes/ )
	   {
		print( "received_bytes=" readable($2) " transmitted_bytes=" readable($4) )
	   }
	else
	   {
		print
	   }
}
Note that one weakness of awk is that it processes fields, and discards the separators between them. This makes it hard to keep the output in the same format as the input. I had to rebuild the entire input line from scratch in the print function. It could be a bit cleaner if you don't require the equal signs:

Code:
{
	if ( $0 ~ /_bytes/ )
	   {
		$2 = readable($2)
		$4 = readable($4)
		print
	   }
	else
	   {
		print
	   }
}
By the way: to be pedantic, the prefixes for byte increments should really be KiB, MiB, etc.:

http://en.wikipedia.org/wiki/Binary_prefix

Last edited by David the H.; 10-21-2011 at 06:22 AM. Reason: fixed some formatting errors
 
1 members found this post helpful.
Old 10-21-2011, 06:08 AM   #5
syg00
LQ Veteran
 
Registered: Aug 2003
Location: Australia
Distribution: Lots ...
Posts: 21,120

Rep: Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120Reputation: 4120
Quote:
Originally Posted by David the H. View Post
Note that one weakness of awk is that it processes fields, and discards the separators between them. This makes it hard to keep the output in the same format as the input. I had to rebuild the entire input line from scratch in the print function. It could be a bit cleaner if you don't require the equal signs:
Or maybe just use the (other) fields it generates, and simply insert the "=" ?.

Nice solution BTW.
 
Old 10-21-2011, 06:15 AM   #6
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
Yeah, of course I could do that. I even did at one point while I was working it out. But it seems to me that if you're dealing with fixed strings anyway, you might as well just put them directly into the script.
 
Old 10-21-2011, 11:01 AM   #7
Xeratul
Senior Member
 
Registered: Jun 2006
Location: UNIX
Distribution: FreeBSD
Posts: 2,657

Original Poster
Rep: Reputation: 255Reputation: 255Reputation: 255
lovely solutions !!

wow

I will test, and will post back So cool. Many thousand thansk
 
Old 10-22-2011, 07:10 AM   #8
H_TeXMeX_H
LQ Guru
 
Registered: Oct 2005
Location: $RANDOM
Distribution: slackware64
Posts: 12,928
Blog Entries: 2

Rep: Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301
Here's my take on it in bash and some awk:

Code:
#!/bin/sh

# make sure we have 2 arguments
if test $# != 2
then
  echo "Usage: $(basename $0) number multiple"
  echo 'number: 3546456567'
  echo 'multiple: b/k/m/g/t'
  exit 1
fi

case "$2" in
	b)
		multiple=0
	;;
	k)
		multiple=1
	;;
	m)
		multiple=2
	;;
	g)
		multiple=3
	;;
	t)
		multiple=4
	;;
	*)
		echo 'ERROR: input not sane'
		exit 1
esac

echo "$1" "$multiple" | awk '
BEGIN{
	multiple[0]="b";
	multiple[1]="k";
	multiple[2]="m";
	multiple[3]="g";
	multiple[4]="t";
}
{
	while ($1 < 1)
	{
		$1*=1024;
		$2--;
	}
	while ($1 >= 1024)
	{
		$1/=1024;
		$2++;
	}
}
END{
	print $1 " " multiple[$2]
}'

exit 0
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
convert number (not hex) into Decimal number drManhattan Programming 10 10-15-2011 08:53 PM
gawk/awk/tcsh - how to convert large number to human readable (Mb,Gb, etc)? BrianK Programming 23 10-30-2010 04:20 AM
Webalizer - howto convert the trafic into human readable? sys7em Linux - Server 3 09-25-2006 04:48 AM
Monitor eth0, number of bytes passed through?? helptonewbie Linux - Networking 4 09-06-2006 10:49 AM
count bytes with awk alaios Linux - General 8 05-13-2003 06:41 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - General

All times are GMT -5. The time now is 09:08 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration