Nabeel Moidu
Nabeel Moidu

Reputation: 222

awk OFS not producing expected value

I have a file

[root@nmk~]# cat file
abc>
sssd>
were>

I run both these variations of the awk commands

[root@nmk~]# cat file | awk -F\>  ' { print $1}' OFS=','
abc
sssd
were

[root@nmk~]# cat file | awk -F\>  ' BEGIN { OFS=","}  { print $1}' 
abc
sssd
were
[root@nmk~]# 

But my expected output is

abc,sssd,were

What's missing in my commands ?

Upvotes: 1

Views: 637

Answers (4)

a5hk
a5hk

Reputation: 7834

awk -F\> -v ORS=""  'NR>1{print ","$1;next}{print $1}' file

to print newline at the end:

awk -F\> -v ORS=""  'NR>1{print ","$1;next}{print $1} END{print "\n"}' file

output:

abc,sssd,were

Upvotes: 2

Mark Reed
Mark Reed

Reputation: 95252

Each line of input in awk is a record, so what you want to set is the Output Record Separator, ORS. The OFS variable holds the Output Field Separator, which is used to separate different parts of each line.

Since you are setting the input field separator, FS, to >, and OFS to ,, an easy way to see how these work is to add something on each line of your file after the >:

awk 'BEGIN { FS=">"; OFS=","} {$1=$1} 1' <<<$'abc>def\nsssd>dsss\nwere>wolf'
abc,def
sssd,dsss
were,wolf

So you want to set the ORS. The default record separator is newline, so whatever you set ORS to effectively replaces the newlines in the input. But that means that if the last line of input has a newline - which is usually the a case - that last line will also get a copy of your new ORS:

awk 'BEGIN { FS=">"; ORS=","}  1' <<<$'abc>def\nsssd>dsss\nwere>wolf'
abc>def,sssd>dsss,were>wolf,

It also won't get a newline at all, because that newline was interpreted as an input record separator and turned into the output record separator - it became the final comma.

So you have to be a little more explicit about what you're trying to do:

  awk 'BEGIN { FS=">"          } # split input on >
      (NR>1) { printf ","      } # if not the first line, print a ,
             { printf "%s", $1 } # print the first field (everything up to the first >) 
         END { printf "\n"     } # add a newline at the end
      ' <<<$'abc>\nsssd>\nwere>'

Which outputs this:

abc,sssd,were

Upvotes: 1

Ed Morton
Ed Morton

Reputation: 203512

You're just a bit confused about the meaning/use of FS, OFS, RS and ORS. Take another look at the man page. I think this is what you were trying to do:

$ awk -F'>' -v ORS=',' '{print $1}' file
abc,sssd,were,$

but this is probably closer to the output you really want:

$ awk -F'>' '{rec = rec (NR>1?",":"") $1} END{print rec}' file
abc,sssd,were

or if you don't want to buffer the whole output as a string:

$ awk -F'>' '{printf "%s%s", (NR>1?",":""), $1} END{print ""}' file
abc,sssd,were

Upvotes: 6

Avinash Raj
Avinash Raj

Reputation: 174706

Through sed,

$ sed ':a;N;$!ba;s/>\n/,/g;s/>$//' file
abc,sssd,were

Through Perl,

$ perl -00pe 's/>\n(?=.)/,/g;s/>$//' file
abc,sssd,were

Upvotes: 0

Related Questions