awk won't print multiple lines 
Author Message
 awk won't print multiple lines

I fairly new to using awk. So forgive me if this sounds rather silly.
I've read the man pages and all online docs that I could find and
still don't understand why it reads one line.
#using the following to read lines of input.
#problem it only displays one record.
awk '{
       BEGIN {FS = ":"  #tried RS = "\f" but didn't work either.
              printf ("Enter a dept number: ")
             }
        FILENAME == "datafile" {
              entry[$3]= $1 $2 $3 $4 $5
               next
              }
        $0~ /^(quit|[qQ]|exit|[xX])$/ {exit}

        $0 != " " {
                    if ($0 in entry) {
                        print entry[$0]
                    } else
                         print $0 "not found"
          }
          {printf("Enter another dept number(q to quit): ")

Quote:
}' datafile -

---------------------------------------------------------------------------
#datafile---
10002:Pentium II:1100:2895:7
10003:Pentium III:1200:2895:5
10004:Celeron:1200:9745:3
10003:Pentium III:1100:2895:5
--------------------------------------------------------------------------
the script works alright expect that if I enter 1100 as user input it
only shows me the last record with 1100 in the $3 field.  How can I
get this to show me the entire record with matching field. I'm only
trying to understand how awk can be useful to me.  thanxs in advance;)


Sat, 22 Oct 2005 02:24:07 GMT  
 awk won't print multiple lines
Your problem is that the array entry is singly dimensioned, subscripted
by $3. You need two arrays, counter and entry. Try something like this:

FILENAME=="datafile" {
        if(counter[$3]="")counter[$3]=0 else counter[$3]++
        entry[$3,counter[$3]] = $0
        next
        }
...
$0!=" " {
          if($0 in counter) {
            for(i=0;i<=counter[$0];i++) {
              print entry[$0,i]
            }
          }
          else {
            print $0 " Not found"
          }
        }

Quote:

> I fairly new to using awk. So forgive me if this sounds rather silly.
> I've read the man pages and all online docs that I could find and
> still don't understand why it reads one line.
> #using the following to read lines of input.
> #problem it only displays one record.
> awk '{
>        BEGIN {FS = ":"  #tried RS = "\f" but didn't work either.
>               printf ("Enter a dept number: ")
>              }
>         FILENAME == "datafile" {
>               entry[$3]= $1 $2 $3 $4 $5
>                next
>               }
>         $0~ /^(quit|[qQ]|exit|[xX])$/ {exit}

>         $0 != " " {
>                     if ($0 in entry) {
>                         print entry[$0]
>                     } else
>                          print $0 "not found"
>           }
>           {printf("Enter another dept number(q to quit): ")
> }' datafile -
> ---------------------------------------------------------------------------
> #datafile---
> 10002:Pentium II:1100:2895:7
> 10003:Pentium III:1200:2895:5
> 10004:Celeron:1200:9745:3
> 10003:Pentium III:1100:2895:5
> --------------------------------------------------------------------------
> the script works alright expect that if I enter 1100 as user input it
> only shows me the last record with 1100 in the $3 field.  How can I
> get this to show me the entire record with matching field. I'm only
> trying to understand how awk can be useful to me.  thanxs in advance;)



Sat, 22 Oct 2005 02:53:36 GMT  
 awk won't print multiple lines

X I fairly new to using awk. So forgive me if this sounds rather silly.
X I've read the man pages and all online docs that I could find and
X still don't understand why it reads one line.
X #using the following to read lines of input.
X #problem it only displays one record.
X awk '{
X        BEGIN {FS = ":"  #tried RS = "\f" but didn't work either.
X               printf ("Enter a dept number: ")
X              }
X         FILENAME == "datafile" {
X               entry[$3]= $1 $2 $3 $4 $5
X                next
X               }
X         $0~ /^(quit|[qQ]|exit|[xX])$/ {exit}
X          
X         $0 != " " {
X                     if ($0 in entry) {
X                         print entry[$0]
X                     } else
X                          print $0 "not found"
X           }
X           {printf("Enter another dept number(q to quit): ")
X }' datafile -
X ---------------------------------------------------------------------------
X #datafile---
X 10002:Pentium II:1100:2895:7
X 10003:Pentium III:1200:2895:5
X 10004:Celeron:1200:9745:3
X 10003:Pentium III:1100:2895:5
X --------------------------------------------------------------------------
X the script works alright expect that if I enter 1100 as user input it
X only shows me the last record with 1100 in the $3 field.  How can I
X get this to show me the entire record with matching field. I'm only
X trying to understand how awk can be useful to me.  thanxs in advance;)

See other replies for more ideas on what is wrong, but here is one.  Awk
is composed of multiple pairs of:

        pattern { action }
        pattern { action )
        ...

Your script starts with '{ ... }'.  That is to say what you have
provided is _ALL_ { action } and no pattern.  This is allowed, and the
pattern is assumed to always be TRUE.

So far so good, _HOWEVER_ inside your { action } is the special pattern
BEGIN.  But BEGIN needs to be outside of the { action } section and in
the pattern section of an awk pattern { action } sequence.  And you have
other pattern { action } pairs inside of the greater '{ ... }'.  This is
just not right.  You should remove those outer { } and just have

awk '
    BEGIN { ... }
    FILENAME == "datafile" { ... }
    $0~ /^(quit|[qQ]|exit|[xX])$/ { ... }
    $0 != " " { ... }
    { printf( ... ) }
' datafile -

Personally, I'm supprised it works at all.

I'm sure there is an awk wizzard out there that can do this in 3 lines
or less, but I tweeked it like this and it does seem to work the way you
described:

awk '
    BEGIN {
        FS = ":"
        printf ("Enter a dept number: ")
    }

    FILENAME == "datafile" {
        if ( $3 in entry )
            entry[$3] = entry[$3] SUBSEP $0
        else
            entry[$3] = $0
        next
    }

    $0 ~ /^(quit|[qQ]|exit|[xX])$/ { exit }

    $0 != " " {
        if ($0 in entry) {
            n = split(entry[$0],recs,SUBSEP)
            for(j=1; j <= n; j++ ) {
                split(recs[j],fields,":")
                print fields[1], fields[2], fields[3], fields[4],
fields[5]
            }
        } else {
            print $0 "not found"
        }
    }
    { printf("Enter another dept number(q to quit): ") }
' datafile -

                                        Bob Harris

PS.  If I've just done your homework, then your job is to understand
_WHY_ the stuff I did, works.



Sat, 22 Oct 2005 10:31:43 GMT  
 awk won't print multiple lines
What's the difference between a single and multidimensioned array this
is what confuses me. Knowing when to use which thanks Robert, for a
easy solution but, I need to know how they work.
Quote:

> Your problem is that the array entry is singly dimensioned, subscripted
> by $3. You need two arrays, counter and entry. Try something like this:

> FILENAME=="datafile" {
>    if(counter[$3]="")counter[$3]=0 else counter[$3]++
>         entry[$3,counter[$3]] = $0
>    next
>    }
> ...
> $0!=" " {
>      if($0 in counter) {
>        for(i=0;i<=counter[$0];i++) {
>          print entry[$0,i]
>        }
>      }
>      else {
>        print $0 " Not found"
>      }
>    }

> > I fairly new to using awk. So forgive me if this sounds rather silly.
> > I've read the man pages and all online docs that I could find and
> > still don't understand why it reads one line.
> > #using the following to read lines of input.
> > #problem it only displays one record.
> > awk '{
> >        BEGIN {FS = ":"  #tried RS = "\f" but didn't work either.
> >               printf ("Enter a dept number: ")
> >              }
> >         FILENAME == "datafile" {
> >               entry[$3]= $1 $2 $3 $4 $5
> >                next
> >               }
> >         $0~ /^(quit|[qQ]|exit|[xX])$/ {exit}

> >         $0 != " " {
> >                     if ($0 in entry) {
> >                         print entry[$0]
> >                     } else
> >                          print $0 "not found"
> >           }
> >           {printf("Enter another dept number(q to quit): ")
> > }' datafile -
> > ---------------------------------------------------------------------------
> > #datafile---
> > 10002:Pentium II:1100:2895:7
> > 10003:Pentium III:1200:2895:5
> > 10004:Celeron:1200:9745:3
> > 10003:Pentium III:1100:2895:5
> > --------------------------------------------------------------------------
> > the script works alright expect that if I enter 1100 as user input it
> > only shows me the last record with 1100 in the $3 field.  How can I
> > get this to show me the entire record with matching field. I'm only
> > trying to understand how awk can be useful to me.  thanxs in advance;)



Sat, 22 Oct 2005 10:53:32 GMT  
 awk won't print multiple lines

Quote:

> > Your problem is that the array entry is singly dimensioned, subscripted
> > by $3. You need two arrays, counter and entry. Try something like this:

> What's the difference between a single and multidimensioned array this
> is what confuses me. Knowing when to use which thanks Robert, for a
> easy solution but, I need to know how they work.

given that your sample is:
line 1: 10002:Pentium II:1100:2895:7
line 2: 10003:Pentium III:1200:2895:5
line 3: 10004:Celeron:1200:9745:3
line 4: 10003:Pentium III:1100:2895:5

using a one-dimensioned array indexed by $3 would give this:
line 1: entry[1100] = "10002:Pentium II:1100:2895:7"
line 2: entry[1200] = "10003:Pentium III:1200:2895:5"
line 3: entry[1200] = "10004:Celeron:1200:9745:3"
line 4: entry[1100] = "10003:Pentium III:1100:2895:5"

see, at line 3 you've *replaced* the previous pentium III record with
the celeron record. What Robert suggests is to use a two-dimensioned
array. On your samples it goes:
line 1: counter[1100]=0; entry[1100,0] = "10002:Pentium II:1100:2895:7"
line 2: counter[1200]=0; entry[1200,0] = "10003:Pentium III:1200:2895:5"
line 3: counter[1200]=1; entry[1200,1] = "10004:Celeron:1200:9745:3"
line 4: counter[1100]=1; entry[1100,1] = "10003:Pentium III:1100:2895:5"

now you've kept both records for the MHz speed.

Laurent



Sat, 22 Oct 2005 17:33:25 GMT  
 awk won't print multiple lines
Well, this is how I did it for school.
BEGIN {
   { FS=":"}
   { print "\t\tTechTron Inventory\n" }
   { "date" | getline d }
   { printf "\t\t %s\n", d }
   ......
   ......
Quote:
}

{ printf "%-04d\t %-30.30s\t %-5d\t %4.2f\n", $3, $2,$1, $5, $4, $5 * $4 }
......
END { print NR, "records processed."
    }
I was just tring to see how I produced a simpler output. Using arrays Guess not.
Quote:



> X I fairly new to using awk. So forgive me if this sounds rather silly.
> X I've read the man pages and all online docs that I could find and
> X still don't understand why it reads one line.
> X #using the following to read lines of input.
> X #problem it only displays one record.
> X awk '{
> X        BEGIN {FS = ":"  #tried RS = "\f" but didn't work either.
> X               printf ("Enter a dept number: ")
> X              }
> X         FILENAME == "datafile" {
> X               entry[$3]= $1 $2 $3 $4 $5
> X                next
> X               }
> X         $0~ /^(quit|[qQ]|exit|[xX])$/ {exit}
> X          
> X         $0 != " " {
> X                     if ($0 in entry) {
> X                         print entry[$0]
> X                     } else
> X                          print $0 "not found"
> X           }
> X           {printf("Enter another dept number(q to quit): ")
> X }' datafile -
> X ---------------------------------------------------------------------------
> X #datafile---
> X 10002:Pentium II:1100:2895:7
> X 10003:Pentium III:1200:2895:5
> X 10004:Celeron:1200:9745:3
> X 10003:Pentium III:1100:2895:5
> X --------------------------------------------------------------------------
> X the script works alright expect that if I enter 1100 as user input it
> X only shows me the last record with 1100 in the $3 field.  How can I
> X get this to show me the entire record with matching field. I'm only
> X trying to understand how awk can be useful to me.  thanxs in advance;)

> See other replies for more ideas on what is wrong, but here is one.  Awk
> is composed of multiple pairs of:

>         pattern { action }
>         pattern { action )
>         ...

> Your script starts with '{ ... }'.  That is to say what you have
> provided is _ALL_ { action } and no pattern.  This is allowed, and the
> pattern is assumed to always be TRUE.

> So far so good, _HOWEVER_ inside your { action } is the special pattern
> BEGIN.  But BEGIN needs to be outside of the { action } section and in
> the pattern section of an awk pattern { action } sequence.  And you have
> other pattern { action } pairs inside of the greater '{ ... }'.  This is
> just not right.  You should remove those outer { } and just have

> awk '
>     BEGIN { ... }
>     FILENAME == "datafile" { ... }
>     $0~ /^(quit|[qQ]|exit|[xX])$/ { ... }
>     $0 != " " { ... }
>     { printf( ... ) }
> ' datafile -

> Personally, I'm supprised it works at all.

> I'm sure there is an awk wizzard out there that can do this in 3 lines
> or less, but I tweeked it like this and it does seem to work the way you
> described:

> awk '
>     BEGIN {
>         FS = ":"
>         printf ("Enter a dept number: ")
>     }

>     FILENAME == "datafile" {
>         if ( $3 in entry )
>             entry[$3] = entry[$3] SUBSEP $0
>         else
>             entry[$3] = $0
>         next
>     }

>     $0 ~ /^(quit|[qQ]|exit|[xX])$/ { exit }

>     $0 != " " {
>         if ($0 in entry) {
>             n = split(entry[$0],recs,SUBSEP)
>             for(j=1; j <= n; j++ ) {
>                 split(recs[j],fields,":")
>                 print fields[1], fields[2], fields[3], fields[4],
> fields[5]
>             }
>         } else {
>             print $0 "not found"
>         }
>     }
>     { printf("Enter another dept number(q to quit): ") }
> ' datafile -

>                                         Bob Harris

> PS.  If I've just done your homework, then your job is to understand
> _WHY_ the stuff I did, works.



Sun, 23 Oct 2005 02:23:04 GMT  
 awk won't print multiple lines

X What's the difference between a single and multidimensioned array this
X is what confuses me. Knowing when to use which thanks Robert, for a
X easy solution but, I need to know how they work.


X > Your problem is that the array entry is singly dimensioned, subscripted
X > by $3. You need two arrays, counter and entry. Try something like this:
X >
X > FILENAME=="datafile" {
X >  if(counter[$3]="")counter[$3]=0 else counter[$3]++
X >         entry[$3,counter[$3]] = $0
X >  next
X >  }
X > ...
X > $0!=" " {
X >    if($0 in counter) {
X >      for(i=0;i<=counter[$0];i++) {
X >        print entry[$0,i]
X >      }
X >    }
X >    else {
X >      print $0 " Not found"
X >    }
X >  }

X > >
X > > I fairly new to using awk. So forgive me if this sounds rather silly.
X > > I've read the man pages and all online docs that I could find and
X > > still don't understand why it reads one line.
X > > #using the following to read lines of input.
X > > #problem it only displays one record.
X > > awk '{
X > >        BEGIN {FS = ":"  #tried RS = "\f" but didn't work either.
X > >               printf ("Enter a dept number: ")
X > >              }
X > >         FILENAME == "datafile" {
X > >               entry[$3]= $1 $2 $3 $4 $5
X > >                next
X > >               }
X > >         $0~ /^(quit|[qQ]|exit|[xX])$/ {exit}
X > >
X > >         $0 != " " {
X > >                     if ($0 in entry) {
X > >                         print entry[$0]
X > >                     } else
X > >                          print $0 "not found"
X > >           }
X > >           {printf("Enter another dept number(q to quit): ")
X > > }' datafile -
X > > --------------------------------------------------------------------------
X > > -
X > > #datafile---
X > > 10002:Pentium II:1100:2895:7
X > > 10003:Pentium III:1200:2895:5
X > > 10004:Celeron:1200:9745:3
X > > 10003:Pentium III:1100:2895:5
X > > --------------------------------------------------------------------------
X > > the script works alright expect that if I enter 1100 as user input it
X > > only shows me the last record with 1100 in the $3 field.  How can I
X > > get this to show me the entire record with matching field. I'm only
X > > trying to understand how awk can be useful to me.  thanxs in advance;)

What I did was _NOT_ a multi-dimensioned array.  I just keep appending
the multiple records to the same array element using a unique separator
so that I could separate them out again.

An awk multi-dimensional array would be something like:

        array[1,1] = "x=1,y=1"
        array[1,2] = "x=1,y=2"
        array[2,1] = "x=2,y=1"
        array[2,2] = "x=2,y=1"

This is a rather regular array, and you could walk through it with
traditional for loop:

        for(j=1; j<=2; j++) {
            for(k=1; k<=2; k++) {
                printf("array[%d,%d] = %s\n", j, k, array(j,k) )
            }
        }

However, if you are going to use the for( j in array ) notation, then
you are going to find that awk _REALLY_ just uses a 1 dimentional array,
but separates the array indexes with the value in SUBSEP.  So if you
want to get the array indexes and the values at each index, you would
need to use a loop more like this:

        for(combined_index in array) {
            printf("show array[")
            n = split(combined_index, indexes, SUBSEP)
            printf("%s",indexes[1])
            for(k=2; k<=n; k++) {
                printf(",%s", indexes[k])
            }
            printf("] = %\n", array(combined_index) )
        }

Think of the _REAL_ array index for array[1,2} as being:

        real_index = "1" SUBSEP "2"
        array[real_index] = "value stored in array at [1,2]"

And because the index to an awk array is really just a string used to
find an entry in a hash table, you can have an array that stores stuff
using a variable number of indexes all at the same time, using numbers
or text strings for each index position, and as long as each
concatenated index is unique each element will be stored in its own
unique location.  For example:

        array[1]     = "x=1"
        array[1,2]   = "x=1,y=2"
        array[2,2]   = "x=2,y=2"
        array[3,3,3] = "x=3,y=3,z=3"
        array["fred",3] = "Fred the 3rd"
        array[1,"George"] = "a George value"

And using the previous for(index in array) example code, the output
should look like:

        show array[1] = x=1
        show array[1,2] = x=1,y=2
        show array[2,2] = x=2,y=2
        show array[fred,3] = Fred the 3rd
        show array[1,George] = a George value

Here are the keys to awk arrays as I know them.

    o  Awk arrays are really 1 dimentional
    o  Awk array indexes are all converted to text
    o  Awk arrays are stored in a hash table structure using the text
       representation of the index as the hash value
    o  Awk multi-dimentional arrays are really 1 dimentional arrays, with
       the indexes converted to text and concatenated into a single
       string using SUBSEP as the separater between each index field.
       The resulting concatenated string is then hashed and used to
       store the value.
    o  The index returned in the for(index in array) statement is the
       concatenated set of index fields for the element.  And the
       individual index fields can be obtained by using
           n=split(index,list,SUBSEP)
           list[1] # left most index
           list[2] # next index to the right
           list[3] # 3rd index
           ...
           list[n] # right most index

Good luck with awk arrays.  They are a very powerful tool and one of the
reasons I got hooked on using awk back in the late 80's.  Perl has even
more storage methods and more ways to access them, but I use awk mostly
because it is a much simpler language (less to remember) and most of my
awk usage is small where performance between awk and perl is not all
that noticable.  But for really large text processing jobs I have used
perl, it is just more work for me to learn and the bang for the buck has
to be sufficient for me to take the effort.   I'm sure if I used perl a
lot more in day to day use, I would learn the key subset of perl
statement that would make me just a productive writing throw away perl
scripts, but alas, it is easier for me to keep using awk :-)

                                Bob Harris



Sun, 23 Oct 2005 06:21:35 GMT  
 awk won't print multiple lines

% Well, this is how I did it for school.
% BEGIN {
%    { FS=":"}
%    { print "\t\tTechTron Inventory\n" }
%    { "date" | getline d }

You should put

  close("date")

at the end of this action, otherwise you'll end up with "" for all but the
first date. Also, decide whether you need to get the date for each
record. If you can get it once in a BEGIN block, that's all the better.

The rest of this doesn't seem to be related to solving your problem.

You're usually better off if you can avoid storing things in arrays.
For instance, in this case you could do something like

 BEGIN {
    printf "Enter department: "
    getline dno < "/dev/tty"
 }

 dno == $3 { print }

If you really need to have it in a loop, you could either store the
data file in an array, or you could re-read it continuously. In
either case, you're likely better off doing all the work in a
BEGIN block

 BEGIN {
    while (1) {
      printf "Enter department: "
      getline dno < "/dev/tty"

      if (dno == 'q') exit

      while (getline < "datafile" > 0) {
         if (dno == $3) { print }
      }
      close("datafile")
   }
 }

or

 BEGIN {
    while (getline < "datafile" > 0) {
       d[$3] = d[$3] $0 "\n"
    }
    close("datafile")

    while (1) {
      printf "Enter department: "
      getline dno < "/dev/tty"

      if (dno == 'q') exit
      printf "%s", d[dno]
   }
 }

--

Patrick TJ McPhee
East York  Canada



Sun, 23 Oct 2005 10:36:05 GMT  
 
 [ 8 post ] 

 Relevant Pages 

1. Sed/AWK - replace positions in multiple lines.

2. Pretty 'print' files from awk

3. awk '{print \$$mynumber}'

4. awk print variable on a new line

5. Print NUM lines of trailing context with awk?

6. Printing multiple lines

7. AWK help needed : The dictionary that won't go away

8. CW 2.003 Multi-Line List Box won't scroll

9. My message text won't fit in a line

10. Last label won't print

11. Why won't Image Print?

12. Printing to a particular printer on Win'98 peer-to-peer Networks

 

 
Powered by phpBB® Forum Software