bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: print keep original format


From: Bob Proulx
Subject: Re: print keep original format
Date: Wed, 25 May 2011 23:35:22 -0600
User-agent: Mutt/1.5.21 (2010-09-15)

lina wrote:
> I don't understand it so well.
> can you help me with this issue?

Okay.  But please don't top-post.  Please just quote the portion of
the message that you want to talk about at that point.

> Andreas Schwab wrote:
> > lina writes:
> >> if I wanna change $4 to B and print the line out
> >> 497  FE  HEM A  43     -12.543  18.254  -4.989  1.00  0.00

You want to change "A" to "B" and those are the same size.  But in
general the sizes might change and you might replace one character
with two or more.  The problem for awk is then should it grow the
field or replace spaces?  Therefore what awk does is to recompute a
new $0 output line based upon the OFS.

> >> for a short awk script, such as
> >> awk '{
> >>       if($2 == 497)
> >>       {
> >>               $5="B"
> >>               print $0
> >>       }
> >> }' $1

You must have left out a field in your data example.  Because in your
example 497 occurs in $1 not $2 and A occurs in $4 not $5.  You must
have another field there.  I will insert an assumed X there to keep
your field numbering and still have a working example.

> >> but the output the space between them has gone.
> >> jt turned out loss the format.
> >> 497 FE HEM B 43 -12.543 18.254 -4.989 1.00 0.00

Right.  This is what Andreas meant when he said:

> > Setting any field causes awk to recompute $0 based on the current value
> > of OFS.  If you want to avoid that you should operate on $0 directly.

> > *Note (gawk) Changing Fields::

The documentation on Changing Fields is also online on the web here:

  http://www.gnu.org/software/gawk/manual/gawk.html#Changing-Fields

Since your OFS (output field separator) is a space character the $0 is
written using each field and separates them using a single space.

To avoid this you can edit $0 directly.

  sub(/ A /," B ",$0)

That will look for space-A-space and replace it with space-B-space
which is an extremely brute force approach to solving your problem but
is illustrative of the type of thing that is meant when we say operate
directly on $0.

  $ echo "X 497  FE  HEM A  43     -12.543  18.254  -4.989  1.00  0.00" \
    | awk '{ if ($2 == 497) { sub(/ A /," B ",$0);print $0; } }'
  X 497  FE  HEM B  43     -12.543  18.254  -4.989  1.00  0.00

That might work okay for you but I worry that it would be too fragile.
Instead I would explicitely write the format for the entire line.

  $ echo "X 497  FE  HEM A  43     -12.543  18.254  -4.989  1.00  0.00" \
    | awk '{
        if ($2 == 497) {
          $5 = "B";
          printf("%s %3s %3s %4s %s %3s %11s %7s %7s %5s %5s\n",
                 $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11);
        }
      }'
  X 497  FE  HEM B  43     -12.543  18.254  -4.989  1.00  0.00

By using printf with explicit field widths everything is formatted in
the desired column.  That is probably how I would do it.

There are probably nicer ways to do it and perhaps someone will
suggest something different.

Bob



reply via email to

[Prev in Thread] Current Thread [Next in Thread]