tags:

views:

31

answers:

3

Hi,

$ echo "a       b" | awk '{print $0; $1="1"; print $0}'
a       b
1 b

I would like to receive formatted output like this:

 a       b
 1       b

Is there easy way to do that (without IFS,OFS changes)? I am changing columns in big table and afterwards it looks ugly. I don't want to reformat each column.

Thanks.

+2  A: 

Probably your best bet is to post-process the output. Perhaps something as simple as:

$ ... | awk ... | column -t

will work. (Unless by "I don't want to format each column" means "I don't want to reformat each row", eg "I don't want to post process". In which case I would ask, "Why not?")

William Pursell
thx :) that what I was looking for.
name
+2  A: 

One possible answer (assuming a fixed number of columns):

echo "a       b" | awk '{print $0; $1="1"; printf("%s\t%s\n", $1, $2)}'

Another possible answer (assuming you don't have a good reason to avoid changing the OFS since, you know, that's the whole POINT of having one!):

echo "a       b" | awk 'BEGIN { OFS="\t" } {print $0; $1="1"; print $0}'

This second one has the advantage of working no matter how many columns your text file has.


Edited to add:

To explain why I think your aversion to using the OFS is bizarre, it's just that the whole reason you're getting that formatting change is because of the OFS. The Output Field Separator (OFS) is by default a single space. When you printed $0 the first time, you'd not made any modifications so $0 was the unaltered line. By changing one of the records you made Awk reassess the line by reassembling $0 from the individual fields. Upon reassembling this, of course, Awk inserted the OFS between fields. Because that's what it's supposed to do. Quote from the relevant man page (man gawk):

Assigning a value to an existing field causes the whole record to be rebuilt when $0 is referenced. Similarly, assigning a value to $0 causes the record to be resplit, creating new values for the fields.

Now I agree that there's a bit of an inconsistency between having the first print and the second treat the fields differently, but that's just the way the language is. The OFS isn't inserted until you actually change the string and it actually calculates the fields and rebuilds and so forth.


Further edited to add:

Watch these:

$ awk 'BEGIN { printf("|%s|\n", OFS) }'
| |
$ awk 'BEGIN { OFS="\t" ; printf("|%s|\n", OFS) }'
|   |
$ 

Is the behaviour of Awk in your first example becoming clearer, as well as understanding why you actually need that OFS or a printf or the like?

JUST MY correct OPINION
thx for the answer. It really brings understanding to the problem.
name
+1  A: 

you can also use substitution

$ echo "a       b" | awk '{print $0; gsub("^[^ \t]","1"); print $0}'
a       b
1       b
ghostdog74
that's what I did at the beginning but the "| column -t" is nicer way.I can change whatever columns I want and at the end still have nice formatted table.
name