LinuxQuestions.org
Visit Jeremy's Blog.
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-15-2012, 12:01 AM   #1
sarenace
Member
 
Registered: Feb 2012
Posts: 57

Rep: Reputation: Disabled
Weird awk behaviour with NOT regexp switch


I'm working with a group of files that have a number identifier in field 1 of line 3. So if I want to pull out lines that only have 180 at this point I would gice the command

Quote:
awk 'FNR==3 && $1 ~ /180/{print}' *
I was under the impression that if I specifically wanted to pull out lines that did NOT have 180 at this point I would enter

Quote:
awk 'FNR==3 && $1 ~ !/180/{print}' *
However, this is pulling out EVERY line, regardless if the field contains 180 or not. Does anyone know whats going on?, again, I only want to pull out lines that do NOT contain 180.
 
Old 05-15-2012, 12:22 AM   #2
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
Try the !~ operator.
 
1 members found this post helpful.
Old 05-16-2012, 08:13 AM   #3
sarenace
Member
 
Registered: Feb 2012
Posts: 57

Original Poster
Rep: Reputation: Disabled
Umm, yes, thats what I've done isnt it?

Quote:
awk 'FNR==3 && $1 ~ !/180/{print}' *
Is this syntax wrong or my use of the operator not correct?
 
Old 05-16-2012, 08:56 AM   #4
colucix
LQ Guru
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983
Quote:
Originally Posted by sarenace View Post
Umm, yes, thats what I've done isnt it?
Nope. Please, try:
Code:
awk 'FNR==3 && $1 !~ /180/' *
as suggested above.
 
1 members found this post helpful.
Old 05-16-2012, 08:57 AM   #5
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,007

Rep: Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192
You need to look a little closer:
Code:
awk 'FNR==3 && $1 ~ !/180/{print}' *

awk 'FNR==3 && $1 !~ /180/{print}' *
 
1 members found this post helpful.
Old 05-16-2012, 08:55 PM   #6
sarenace
Member
 
Registered: Feb 2012
Posts: 57

Original Poster
Rep: Reputation: Disabled
Why does that work? Whats the difference between !~ and ~! ?
 
Old 05-16-2012, 09:59 PM   #7
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 sarenace View Post
Why does that work? Whats the difference between !~ and ~! ?
In awk, ~ is the regular expression match operator. !~ is the regular expression no-match operator.

There is no ~! operator at all. You cannot modify a regular expression by prepending ! to it. It is not in any regular expression rules. In general, prepending ! in front of a regular expression is an error.

To awk, constant regular expressions like /pattern/ are treated according to the same rules that apply to variables. In fact, if you use /pattern/ where a regular expression is not expected (for example, print /foo/), it evaluates to 0. (In awk, logical "false" is represented using 0, and "true" using 1 (or any nonzero value). Same rules ANSI C uses.)

When you specify ~ !/pattern/, the not operator (!) applies to /pattern/ first. Because the not operator has nothing to do with regular expressions, the /pattern/ is evaluated as a variable, yielding 0. The not operator inverts that to 1. The result is the same as if you had written ~ 1. Because of the rules awk uses, the right side may be a variable or a string, and according to awk promotion rules, that 1 is converted to a string. The end result is just as if you had written ~ "1" or ~ /1/.

In other words, according to awk rules, (something ~ !/pattern/) is the exact same thing as (something ~ /1/) .
 
2 members found this post helpful.
Old 05-18-2012, 12:54 AM   #8
sarenace
Member
 
Registered: Feb 2012
Posts: 57

Original Poster
Rep: Reputation: Disabled
Thank you. That's an extremely thorough and easy to understand explanation.
 
  


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
awk regexp for uuid webhope Programming 82 05-03-2010 05:17 AM
[SOLVED] Migrate Regexp from SED to AWK cgcamal Programming 9 04-23-2010 10:32 PM
awk regexp for one character match nemobluesix Linux - General 7 02-16-2009 10:50 PM
javascript regexp - strange exec behaviour, or space matching? jkobrien Programming 3 08-20-2008 07:09 AM

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

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