LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-11-2011, 10:17 AM   #1
dazdaz
Member
 
Registered: Aug 2003
Location: Europe
Distribution: RHEL, CentOS, Ubuntu
Posts: 333

Rep: Reputation: 17
matching numbers with nawk


Hi

I am struggling to understand why nawk matches values that are either 1 or 2 digits in length, but not 100 (3 digits). Am I missing something obvious ? Should I use substr to remove the % ?
I am sure it's something to do with character and string matching behaviour with nawk.

Code:
$ echo "/dev/vx/dsk/dg/volume 4194304 4194304       0   99%    /opt/mountpoint" | nawk '{if ( $5 >= 99 ) {printf "%s\n", $0}}'
        /dev/vx/dsk/dg/volume 4194304 4194304       0   99%    /opt/mountpoint


$ echo "/dev/vx/dsk/dg/volume 4194304 4194304       0   100%    /opt/mountpont" | nawk '{if ( $5 >= 99 ) {printf "%s\n", $0}}'
$

Would appreciate any input.

Last edited by dazdaz; 05-11-2011 at 11:26 AM.
 
Old 05-11-2011, 11:53 AM   #2
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 remember seeing something like this before. Yes, I believe the % sign makes awk treat it as a string comparison. You'll have to remove it before it will compare them numerically.
 
1 members found this post helpful.
Old 05-11-2011, 02:33 PM   #3
dazdaz
Member
 
Registered: Aug 2003
Location: Europe
Distribution: RHEL, CentOS, Ubuntu
Posts: 333

Original Poster
Rep: Reputation: 17
So I need to use gsub to strip out the % from field 5 ? Unfortunately I am not entirely sure of the correct syntax to do this. I've tried a few variations.

Code:
echo "/dev/vx/dsk/dg/volume 4194304 4194304       0   100%    /opt/mountpont" | awk '{num = gsub(/%/, "",$5); if ($num >= 99 ) {printf "%s\n", $0}}'

Last edited by dazdaz; 05-11-2011 at 02:54 PM.
 
Old 05-11-2011, 10:26 PM   #4
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,007

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
Depending on if you wish to do more with num than this comparison, you could just use gensub in the comparison:
Code:
awk 'gensub(/%/,//,"g",$5) >= 99' file
 
Old 05-12-2011, 12:11 PM   #5
dazdaz
Member
 
Registered: Aug 2003
Location: Europe
Distribution: RHEL, CentOS, Ubuntu
Posts: 333

Original Poster
Rep: Reputation: 17
Hi Grail,

I tried the following using gensub, however it does'nt seem to work as expected, i.e. it does'nt work with 3 digits.

Code:
echo "/dev/vx/dsk/dg/volume 4194304 4194304       0   100%    /opt/mountpont" | awk '{if ( gensub(/%/,//,"g",$5) >= 99 ) {printf "%s\n", $0}}'
What is even stranger is that the % is not stripped out
Code:
echo "/dev/vx/dsk/dg/volume 4194304 4194304       0   101%    /opt/mountpont" | awk 'gensub(/%/,//,"g",$5)'
/dev/vx/dsk/dg/volume 4194304 4194304       0   101%    /opt/mountpont
 
Old 05-13-2011, 01:39 AM   #6
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,007

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
Yeah that would be my bad on 2 accounts

1. the second lot of // should be ""
2. gensub is returning a string

Try:
Code:
echo "/dev/vx/dsk/dg/volume 4194304 4194304       0   100%    /opt/mountpont" | awk 'int(gensub(/%/,//,"g",$5)) >= 99'
 
1 members found this post helpful.
Old 05-13-2011, 07:57 AM   #7
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
If you'd rather use sub or gsub you should copy the contents of the field into a variable and manipulate that instead.
Code:
awk '{ x=$5 ; gsub( /%/ , "" , x ) ; if ( x >= 99 ) { printf "%s\n" , $0 } }'
Unlike gensub, sub/gsub directly alter the input string, so using a copy of the field keeps the original safe and sound.

http://www.gnu.org/software/gawk/man...ring-Functions

There may of course be some subtle differences between gawk and nawk, but I don't have nawk available to test.
 
1 members found this post helpful.
Old 05-13-2011, 09:35 AM   #8
dazdaz
Member
 
Registered: Aug 2003
Location: Europe
Distribution: RHEL, CentOS, Ubuntu
Posts: 333

Original Poster
Rep: Reputation: 17
Thanks for all the reply's. For some reason I prefer the gsub method, by assigning the value to a variable and then manipulating that.
 
Old 05-13-2011, 12:11 PM   #9
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by dazdaz View Post
I am struggling to understand why nawk matches values that are either 1 or 2 digits in length, but not 100 (3 digits).
Explicitly convert the field to a number first, int($1) if it must be an integer, or (1.0*$1) for real numbers. Note that you must keep the parenthesis in the latter one, otherwise it will not work.

In your case,
Code:
nawk '{ if ( (1.0*$5) >= 99 ) printf "%s\n", $0 }'
should work fine. I find this much simpler than filtering the field with regular expressions.
 
1 members found this post helpful.
Old 05-14-2011, 01:46 PM   #10
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
Thank you, NA. That's interesting. I didn't know you could do arithmetic operations on fields containing non-numeric characters. Convenient.

I see that it only works properly if the field starts with an number, however, and it only operates on the initial number string. So a field containing "10foo20" will be treated as "10", and "foo10foo20" will be seen as "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 Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Perl Script needed to be reversed to output matching, not non-matching 0bfuscated Programming 2 07-20-2010 10:51 AM
nawk in linux joyrock Programming 3 02-10-2010 09:28 AM
Need help with nawk ryanlum Linux - General 3 04-07-2008 04:02 PM
Nawk output omega71122 Solaris / OpenSolaris 3 08-16-2005 03:40 PM
nawk not available raees Linux - Software 3 05-02-2005 03:49 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 07:29 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