Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does an awk field assignment lose the output field separator?

Tags:

awk

This command works. It outputs the field separator (in this case, a comma):

$ echo "hi,ho"|awk -F, '/hi/{print $0}'
hi,ho

This command has strange output (it is missing the comma):

$ echo "hi,ho"|awk -F, '/hi/{$2="low";print $0}'
hi low

Setting the OFS (output field separator) variable to a comma fixes this case, but it really does not explain this behaviour.

Can I tell awk to keep the OFS?

like image 691
jcalfee314 Avatar asked May 05 '14 18:05

jcalfee314


People also ask

What is output field separator in awk?

5.3 Output Separators In the output, the items are normally separated by single spaces. However, this doesn't need to be the case; a single space is simply the default. Any string of characters may be used as the output field separator by setting the predefined variable OFS .

How do you use the field separator in awk?

You can define a field separator by using the "-F" switch under the command line or within two brackets with "FS=...". Above the field, boundaries are set by ":" so we have two fields $1 which is "1" and $2 which is the empty space.

Which separates the fields when awk prints the default as a blank space?

By default, fields are separated by whitespace, like words in a line. Whitespace in awk means any string of one or more spaces, TABs, or newlines; other characters that are considered whitespace by other languages (such as formfeed, vertical tab, etc.)

What is the default input field separator used by awk programming language?

The default field delimiter or field separator (FS) is [ \t]+ , i.e. one or more space and tab characters.


2 Answers

When you modify the line ($0) awk re-constructs all columns and puts the value of OFS between them which by default is space. You modified the value of $2 which means you forced awk to re-evaluate$0.

When you print the line as is using $0 in your first case, since you did not modify any fields, awk did not re-evaluated each field and hence the field separator is preserved.

In order to preserve the field separator, you can specify that using:

BEGIN block:

$ echo "hi,ho" | awk 'BEGIN{FS=OFS=","}/hi/{$2="low";print $0}'
hi,low

Using -v option:

$ echo "hi,ho" | awk -F, -v OFS="," '/hi/{$2="low";print $0}'
hi,low

Defining at the end of awk:

$ echo "hi,ho" | awk -F, '/hi/{$2="low";print $0}' OFS=","
hi,low
like image 113
jaypal singh Avatar answered Jun 20 '23 05:06

jaypal singh


You first example does not change anything, so all is printed out as the input.
In second example, it change the line and it will use the default OFS, that is (one space)
So to overcome this:

echo "hi,ho"|awk -F, '/hi/{$2="low";print $0}' OFS="," 
hi,low
like image 41
Jotne Avatar answered Jun 20 '23 04:06

Jotne