I want to grab a block of text from 'from_pattern' to 'to_pattern',
and with that block of text I want to print to screen the last column
of those lines containing the secondary patterns 'local_pattern1' and
'local_pattern2'. I.e. something like this:
#
/from_pattern/,/to_pattern/ {
/local_pattern1/ printf ($NF" ")
/local_pattern2/ printf ($6"\n")
}
#
This keeps giving me syntax errors though. Is it even possible to use
nested ranges in awk or do I have to use sed for this?
No. Once you are inside {}, you have to use ordinary code. There only
one level of "automatic" pattern matching.
So, the above becomes:
/from_pattern/,/to_pattern/ {
if (/local_pattern1/) printf ($NF" ")
if (/local_pattern2/) printf ($6"\n")
}
Side comments:
1) GAWK (and most "normal/standard" AWKs) allow the: if (/foo/)
syntax - i.e., a reg exp appearing by itself is shorthand for:
$0 ~ /foo/
But TAWK requires the "$0 ~" to be explicitly spelled out.
2) The usual comments about mis-use of printf().
Here's what I want to do:
I want to grab a block of text from 'from_pattern' to 'to_pattern',
and with that block of text I want to print to screen the last column
of those lines containing the secondary patterns 'local_pattern1' and
'local_pattern2'. I.e. something like this:
#
/from_pattern/,/to_pattern/ {
/local_pattern1/ printf ($NF" ")
/local_pattern2/ printf ($NF"\n")}
Thank you!
About side comment 2) What would be a better way of using printf here?
He probably means to specify a format string
printf ("%s ", $NF)
printf ("%s\n", $6)
(But maybe he's nit-picking about the brackets, dunno.)
Janis
> No. Once you are inside {}, you have to use ordinary code. There only
> one level of "automatic" pattern matching.
Just thinking aloud here about an example recently posted by Janis...
By 'automatic', do you mean only between BEGIN{} & END{} and then,
only without the middle {}, ie:
BEGIN{}
'automatic'
END{}
but not:
BEGIN{}
{automatic}
END{}
--
later on,
Mike
What about (untested):
#
!(/from_pattern/,/to_pattern/) { next }
/local_pattern1/ { printf "%s ", $NF }
/local_pattern2/ { printf "%s\n", $NF }
#
Grant.
--
http://bugsplatter.id.au
If your 'automatic' is a condition, e.g. something like /pattern/ or
flag1||flag2 then you are correct. The key part in Kenny's posting is
"ordinary code". Mind that an awk program is basically[*] a sequence of
condition { action }
constructs. That "action" is a conventional "ordinary code" as found in
many imperative (procedural) programming languages, "condition", OTOH,
is an expression that evaluates to a predicate (effectively a boolean
value). /pattern/ is such an expression (it can be also viewed as an
implicit shortcut for $0~/pattern/. But neither /pattern/ alone nor
$0~/pattern/ alone is a valid statement ("ordinary code") for an action;
you need to embed it in a control construct if($0~/pattern/) to be a
valid action.
N.B.: In case I see, in awk, something like
{
if ($0~/p/) { x="hi" }
if ($0~/q/) { y="there" }
if (r) { z="!" }
}
I often rewrite it to
/p/ { x="hi" }
/q/ { y="there" }
r { z="!" }
which has less syntactical ballast and is therefore much clearer. For
people who are fixed to their imperative programming skill and new to
awk that syntax might not be obvious even though it's one of the basics
in awk and typically easily explained.
This syntactical clearer way to write programs has its limits, though,
where deeply nested control constructs are involved. OTOH, I've also
often seen convoluted awk programs with deeply nested control structures
that could be simplified to something that was again representable in
this cute awk'ish way.
Let me close my rant with a quote from an interview with A.Robbins at
awk.info (http://awk.info/?news/robbinsTalks):
Q: In retrospect, what are the best/worst features of gawk?
A: The best feature is the pattern/action paradigm. The
implicit read-a-record loop is wonderful. This is the
language's data-driven nature, as opposed to the
imperative nature of most languages. [...]
(Which is apparently not only related to gawk but to awk in general.)
Janis
[*] There are also function definitions.
The above, if it works (I'm truly not sure what awk does with a
negated range expression like that), would presumably mean "if the
current record is NOT within the desired range then do NOT continue to
process this record" so that's a double negative which makes the code
hard to understand. Rather than:
!(/from_pattern/,/to_pattern/) { next }
/local_pattern1/ { printf "%s ", $NF }
/local_pattern2/ { printf "%s\n", $NF }
for clarity I'd write it as:
/from_pattern/ { inRange=1 }
inRange && /local_pattern1/ { printf "%s ", $NF }
inRange && /local_pattern2/ { printf "%s\n", $NF }
/to_pattern/ { inRange=0 }
or as the OP originally structured it:
/from_pattern/,/to_pattern/ {
if (/local_pattern1/) { printf "%s ", $NF }
if (/local_pattern2/) { printf "%s\n", $NF }
}
This "if"s don't seem like too much of a burden there.
Regards,
Ed.
Great post. Much brain food to chew on here, thank you.
> {
> if ($0~/p/) { x="hi" }
> if ($0~/q/) { y="there" }
> if (r) { z="!" }
> }
>
> I often rewrite it to
>
> /p/ { x="hi" }
> /q/ { y="there" }
> r { z="!" }
Yes, understood (I'm on the right track then).
> might not be obvious...
Actually, its usage is obvious to me (nomenclature not withstanding),
its context that I seem to be lacking. From what I've studied up to
this point, the main difference I note is the lack of opening/closing
curly brackets when using the '/p/ {a}' paradigm.
Seems like a superb way to code an expression, 'cute' or not. A simple
boolean notation denoting 'if condition then do_something'.
Thanks again, Janis. Appreciate all the insight laden responses here.
--
later on,
Mike
So, what does Arnold say is/are the *worst* feature(s) of gawk?
In a nutshell... (see above link for the complete response)
* lack of an explicit concatenation operator
* lack of real multi-dimensional arrays
* i18n on "awk level" (a "waste of time")
* IGNORECASE ("a huge pain to get right")
* lack of extensibility concept
Some of the features (or lack thereof) are just inherited from
original awk language.
Janis
printf ($NF" ") will crash the program if the last field is "%s".
Correct:
printf "%s", $NF
And printf ($6"\n") should simply be
print $6
Give the man a cigar!
You might have to take it back because his reponse to the question of
"how do I use awk to skip leading fields" in another comp.lang.awk
thread was:
ruby -pne 'sub(/^\s*\S+\s+/, "")' file
;-).
Ed.
Yes, I saw that. And I thought about doing a topicality flame on it,
but didn't bother.
Really, though, he just left off the AWK wrapper. He meant to say:
awk 'BEGIN {system("ruby -pne '"'"'sub(/^\s*\S+\s+/, \"\")'"'"' file")}'