Reputation: 2257
I'm trying to write two awk commands to check a file to meet both conditions.
Example:
test deny=1
test2 deny=0
test deny=4
#test=3 deny=0
test deny=44
I want it to display:
test deny=44
test2 deny=0
Here is my current regex that doesn't appear to be outputting that correctly:
awk '$1 ~ /[^#]*/ && ! /deny=([1-9]|10)/' /etc/pam.d/system-auth
Here is my current line for this output
awk '$1 ~ /[^#]*/ && /deny=1[1-9]/ && /deny=[2-9][0-9]/' /etc/pam.d/system-auth
Any thoughts on how to improve these? I wanted to see how this works in shell/bash before trying to port it to ruby.
Upvotes: 1
Views: 73
Reputation: 203334
It always surprises me when people say they need a numeric comparison and then look for a way to cludge it with regexps. If you want to compare numbers, use a numeric comparison:
$ awk 'match($0,/^[^#]*deny=([0-9]+)/,a) && (a[1]==0 || a[1]>10)' file
test2 deny=0
test deny=44
$ awk 'match($0,/^[^#]*deny=([0-9]+)/,a) && (a[1]>=1 && a[1]<=10)' file
test deny=1
test deny=4
The above uses GNU awk for the 3rd arg to match(), with other awks it'd be substr() or sub() and a variable, e.g.:
$ awk '{n=$0} sub(/^[^#]*deny=/,"",n) && (n+0==0 || n+0>10)' file
test2 deny=0
test deny=44
$ awk '{n=$0} sub(/^[^#]*deny=/,"",n) && (n+0>=1 && n+0<=10)' file
test deny=1
test deny=4
Note that you need to add zero in the non-gawk version since the first operation we do on n
is a string one (sub()
) so at that point awk "knows" that n
contains a string (despite it "looking like" a number which is why the gawk version doesn't require this special treatment) and so to use it as a number afterwards we need to explicitly cast it to a number by doing a numeric operation (+
) on it.
Upvotes: 1
Reputation: 785068
You can use this awk
command with custom field separator:
awk -F '[= \t]+' '!/^[ \t]*#/ && $2 == "deny" && ($3==0 || $3>10)' file
test2 deny=0
test deny=44
-F '[= \t]+'
sets input field separator as =
or a space or a tab!/^[ \t]*#/
will match anyline that is not commentedEDIT:
As per comments below if deny
can appear anywhere in input then use:
grep -E '^([[:blank:]]*[^#].*)?deny=(0\b|1[1-9]|[2-9][0-9])' file
test2 deny=0
test deny=44
(0\b|1[1-9]|[2-9][0-9])
will match either 0
or any 2 digit number greater than 10
.
Upvotes: 1
Reputation: 246774
deny=44
DOES match the regex /deny=([1-9]|10)/
-- you need a word anchor there: /deny=([1-9]|10)\>/
#test=3
DOES match the regex /[^#]*/
because there are zero or more non-"#" charactersYou want
awk '$1 !~ /^#/ && ! /deny=([1-9]|10)\>/'
Looks like you can benefit from a regular expression tutorial online. See https://stackoverflow.com/tags/regex/info
Upvotes: 0