how to pass multiple time over one file

26 views
Skip to first unread message

vinod

unread,
Apr 14, 2005, 8:04:03 PM4/14/05
to
Hi,
I want to pass over a file multiple time, the next pass over file shud
start after the current line.
for example i have following file

begin 1
begin 2
end 1
begin 3
begin 1
end 1
begin 4
end 2
end 3

i want to match the "begin" & "end" for particular number & if "end" is
matching do some processing. For particular number the "begin" & "end"
might be multiple times thts why for each "begin" line i want to check
whole file from next statement & find "end" for it.

Thanks,
Vinod

Ed Morton

unread,
Apr 14, 2005, 10:03:03 PM4/14/05
to

The easiest way is to list the same file name multiple times, e.g.:

awk '...' file1 file1 file1

You can save the line number in a variable that'll be persistent across
all passes of the file. Provide some more details if you want more help.

Ed.

vinod

unread,
Apr 20, 2005, 10:57:50 AM4/20/05
to

Thanks Ed for ur reply
let me explain u what i wanted to do
consider 1st file pointer which is going over a file. lets consider
that file pointer is @ "begin 1" location i want this file pointer to
remain @ this position & start a new 2nd file pointer which is going to
pass over file from the next line of "begin 1". After completing the
pass of 2nd file pointer advanced the 1 file pointer to next line i.e.
"begin 2" again start the 2 file pointer which is going to start now
from the next line of "begin 2" & pass over whole file. again
completing the pass of 2 file pointer advance the 1 file pointer to
next line & so on.... upto the 1st file pointer completes the pass over
whole file.
So i want to start second file pointer for each line of the first
file pointer.

thanks,
Vinod

Ed Morton

unread,
Apr 20, 2005, 9:07:14 PM4/20/05
to

vinod wrote:

Not exactly trivial. This won't exactly do it, but here's a script I
wrote a while back to recursively include files use an "include" directive:

awk 'function read(file) {
while ( (getline < file) > 0) {
if ($1 == "include") {
read($2)
} else {
print
}
}
close(file)
}
BEGIN{
read(ARGV[1])
ARGV[1]=""
exit
}' a.txt

so that if "a.txt" contained:

1
2
include b.txt
9
10

the output would be the first 2 lines of a.txt then the contents of
b.txt, then the last 2 lines of a.txt.

You can probably do what you want with a similair recursive approach.
You probably need to remember line numbers before you descend since
you'll need to keep closing the input file and starting reading it from
the beginning on every descent and ascent.

Ed.

Ed Morton

unread,
Apr 23, 2005, 5:09:23 PM4/23/05
to

Ed Morton wrote:

I had another thought on this one. Instead of a recursive descent
algorithm, you could add a new instance of the input file for every
"begin" statement. This example:

awk 'function addPass() {fp[++passes]=FNR;ARGV[ARGC++]=ARGV[1]}
function skipHead(_s) {pass++;while(_s++<fp[pass])getline}
function skipTail(_s)
{addPass();_s=fp[pass]=FNR;while(_s++<nr)getline}
BEGIN{ addPass() }
NR==FNR { nr++; if ($1=="begin") addPass(); next }
FNR==1 { print "----"; skipHead() }
{ print pass ":" FNR ":" $0 }
$1 == "begin" { skipTail() }' $1

probably isn't exactly what you want, but it should get you close. The
first time reading the input file, all it does is find out where the
"begin" statements are and stores their line numbers in the file pointer
(fp) array and adds a new ARGV[] entry with a duplicate file name. After
that awk goes through ARGV[] as normal, each time skipping lines until
it reaches the "fp" entry for that file name instance. You probably need
to throw a "close()" in there somewhere and figure out when you want to
print begin/end lines vs skip them until next the next instance of the
file. I'd be interested in seeing the finial version if you get this
working the way you want.

Ed.

John Savage

unread,
Apr 25, 2005, 8:00:07 PM4/25/05
to
"vinod" <vinod....@gmail.com> writes:
>> vinod wrote:
>> > Hi,
>> > I want to pass over a file multiple time, the next pass over file shud
>> > start after the current line.
>> > for example i have following file

Can your file be guaranteed small enough that it can be held in an array
for repeated reading by the particular awk you'll be using?

Test your worst case using: awk 'a[i++]=$0' file
then post back here whether it executes without error messages.
--
John Savage (my news address is not valid for email)

Ed Morton

unread,
Apr 25, 2005, 8:15:28 PM4/25/05
to

John Savage wrote:
> "vinod" <vinod....@gmail.com> writes:
>
>>>vinod wrote:
>>>
>>>>Hi,
>>>>I want to pass over a file multiple time, the next pass over file shud
>>>>start after the current line.
>>>>for example i have following file
>
>
> Can your file be guaranteed small enough that it can be held in an array
> for repeated reading by the particular awk you'll be using?
>
> Test your worst case using: awk 'a[i++]=$0' file
> then post back here whether it executes without error messages.

In addition to the memory issue, the problem with that approach is it
makes your script a bit lengthier and messier, e.g. this:

awk '...
/whatever/' file

has to be written as:

awk '...
END{ for (j=1; j<=i; j++) if (a[j] ~ /whatever/) print }' file

Regards,

Ed.

Reply all
Reply to author
Forward
0 new messages