Is there a possibility to undo a getline call that the actual
line is processed again.
I have got a script which look like:
/^address1/ {
# do something
next;
}
/^address2/ {
# do something
next;
}
# default rule
{
while( $1 == "0" && $2 < 100 ) {
print $0 > output_file;
getline;
}
print "some contents" > output_file;
# add this point the actual line needs be checked again
# for address1 and address2 so actually a jump to the
# beginning of script is needed
}
Any hints or ideas?
Thanks in advance.
Regards, Uwe
--
,_,
(O,O) mailto:keinfruehst...@gmx.net
( ) http://www.tu-chemnitz.de/~uwp
-"-"---------------------------------------------
[chop: rules]
> # default rule
> {
> while( $1 == "0" && $2 < 100 ) {
> print $0 > output_file;
> getline;
> }
> print "some contents" > output_file;
>
> # add this point the actual line needs be checked again
> # for address1 and address2 so actually a jump to the
> # beginning of script is needed
>
> }
Maybe put the "default rule" first in the script?
Another idea might be to drop the whole while loop thing and use a
pattern instead.
$1 == "0" && $2 < 100 {
print > output_file
}
getline doesn't undo, AWK doesn't go back.
So, if you need prior info, you have to save the state from prior lines, or
save the lines themselves. If you need repeated actions, you need to repeat
them yourself.
/^address1/ { something(); next }
/^address2/ { somethingElse(); next }
{
while( $1 == "0" && $2 < 100 ) {
print $0 > output_file;
getline;
}
print "some contents" > output_file;
}
# The "actual line" at this point is the first line that
# failed to match the $1=="0" and 2<100 criteria.
/^address1/ { something(); next }
/^address2/ { somethingElse(); next }
Note that in this case, you CAN'T just move the /address/ tests to the end,
because the default case will always print "some contents" to the
output_file for each line, whereas for initial /address/ lines, it doesn't
in the current state.
There may be an easier way to do what you want; why don't you post some
sample data and expected results?
- Dan
You can't put the default rule first, because it would print "some contents"
for every input line, whereas in the original code, that would not happen on
initial /address/ lines.
Using another pattern is a good idea, however, note that the /address/
strings need to be ignored while the loop condition is true, and this
introduces some complex switching on a variable that tells the address
patterns to be ignored in what WAS the while loop. This accomplishes
something like that, but I'm not sure if it is the true answer taht Uwe
Pross wanted....
!ok && /^address1/ { something(); next }
!ok && /^address2/ { somethingElse(); next }
$1 == "0" && $2 < 100 { ok = 1; print > output_file; next }
{ ok = 0 }
!ok { print "some contents" > output_file; }
- Dan
You cannot actually "undo" a getline in awk, but you can implement
the pushback or "un-read" of an input line yourself with a pair of
cooperating functions. There's a good example of this on p. 105 of
_The AWK Programming Language_ (ISBN 0-201-07981-X). Here are the
two functions (from <http://cm.bell-labs.com/cm/cs/who/bwk/awkcode.txt>):
function getone(f, gp, n) { # get next line in gp[n]
if (eofstat <= 0) # eof or error has occurred
return 0
if (ungot) { # return lookahead line if it exists
gp[n] = ungotline
ungot = 0
return 1
}
return eofstat = (getline gp[n] <f)
}
function unget(s) { ungotline = s; ungot = 1 }
And here is the authors' explanation of the code:
Before reading a new line, getone checks to see if there is
a line that has already been read and stored by unget, and
if there is, returns that instead of reading a new one.
Pushback is a different way of dealing with a problem that
we encountered earlier, reading one too many inputs. In
the control-break programs early in this chapter, we delayed
processing; here we pretend, through a pair of functions,
that we never even saw the extra input.
--
John
A better question is why you need the getline function at all.
It seems that eliminating it would make your script work just as
you wish.
Chuck Demas
Chuck Demas
--
Eat Healthy | _ _ | Nothing would be done at all,
Stay Fit | @ @ | If a man waited to do it so well,
Die Anyway | v | That no one could find fault with it.
de...@tiac.net | \___/ | http://www.tiac.net/users/demas
I thought so ;-|
> So, if you need prior info, you have to save the state from prior lines, or
> save the lines themselves. If you need repeated actions, you need to repeat
> them yourself.
>
> /^address1/ { something(); next }
> /^address2/ { somethingElse(); next }
> {
> while( $1 == "0" && $2 < 100 ) {
> print $0 > output_file;
> getline;
> }
> print "some contents" > output_file;
> }
> # The "actual line" at this point is the first line that
> # failed to match the $1=="0" and 2<100 criteria.
> /^address1/ { something(); next }
> /^address2/ { somethingElse(); next }
This is the easiest and most strait forward solution.
> There may be an easier way to do what you want; why don't you post some
> sample data and expected results?
The awk-script is intended to add shadow to xfig-files. It has
become quite a large so I did not want to post it. By now it
works quite well apart from one special case for which the
actual line taken by the getline function has to be processed
again. Maybe I can restructre it. If not I have to move the
functionality to functions and put some rules after the default
rule.
Just in case somebody wants to see the script I put it on the
web:
http://www-user.tu-chemnitz.de/~uwp/download/addShadowToFig.awk
Thanks for all hints.
On 24 Sep 2002 08:38:13 GMT, Uwe Pross wrote:
> http://www-user.tu-chemnitz.de/~uwp/download/addShadowToFig.awk
I've looked at the program. I think the problem is that your
"default rule" is not only handling default lines/objects, it is
also responsible for adding some stuff to the header.
This is what you have to get rid of.
So you probably have to redesign the program.
I think that your program could fit into this scheme:
# Not mentioning the BEGIN/END rules.
FNR==1 { ... } # process header
# now follow the rules for various objects:
/^#.../ {...}
....
# the default rule, if we get here:
{...}
Ideas about FIG file processing:
1) I'd not bother with keeping the colour pseudo-objects ordered.
The format specification doesn't require it.
So I'd just put the new colour pseudo-objects just after the header
into the FNR==1 rule (see above).
2) If you want to have the colours sorted, you can use this set of
rules:
BEGIN { addedColours = 0 ; maxColour = 99 }
/^0 / {
# seen Colours
if (maxColour < $2) {
if (addedColours == 2)
print "error!!!"
maxColour = $2
}
if (addedColours == 0)
addedColours = 1
}
addedColours == 1 && !/^0 / {
# seen some colours but this is non-colour object
for (i=0; i<16; i++) {
print 0, maxColour + i, ... # write all new colours
}
}
This adds the new colours just after the last colour, _supposing_
they are in one cluster (which is not necessary).
3) To process a general FIG file with colour pseudo-objects spread
around the whole file, you have to read it twice (and put the colours
at the beginning, to be sure that they are defined when you use them
first).
BTW: *A typo:* your program contains comment "0 3 spline" which
should in fact be "3 0 spline".
HTH,
Stepan Kasal
How about
awk '
/^address1/ {
if ( ok ){
print "some contents" > output_file
ok = 0
}
# do something
next
}
/^address2/ {
if ( ok ){
print "some contents" > output_file
ok=0
}
# do something
next
}
$1 == "0" && $2 < 100 {
ok = 1
print $0 > output_file
next
}
' SomeFile