53

Here is the input(sample):

name1@gmail.com|com.emailclient.account
name2@msn.com|com.socialsite.auth.account

I'm trying to achieve this:

Emailclient name1@gmail.com
Socialsite name2@msn.com

If I use AWK like this:

cat foo | awk 'BEGIN{FS="|"} {print $2 " " $1}'

it messes up the output by overlaying field 1 on the top of field 2.

Any tips/suggestions? Thank you.

Sazzy
  • 1,924
  • 3
  • 19
  • 27

4 Answers4

89

A couple of general tips (besides the DOS line ending issue):

cat is for concatenating files, it's not the only tool that can read files! If a command doesn't read files then use redirection like command < file.

You can set the field separator with the -F option so instead of:

cat foo | awk 'BEGIN{FS="|"} {print $2 " " $1}' 

Try:

awk -F'|' '{print $2" "$1}' foo 

This will output:

com.emailclient.account name1@gmail.com
com.socialsite.auth.accoun name2@msn.com

To get the desired output you could do a variety of things. I'd probably split() the second field:

awk -F'|' '{split($2,a,".");print a[2]" "$1}' file
emailclient name1@gmail.com
socialsite name2@msn.com

Finally to get the first character converted to uppercase is a bit of a pain in awk as you don't have a nice built in ucfirst() function:

awk -F'|' '{split($2,a,".");print toupper(substr(a[2],1,1)) substr(a[2],2),$1}' file
Emailclient name1@gmail.com
Socialsite name2@msn.com

If you want something more concise (although you give up a sub-process) you could do:

awk -F'|' '{split($2,a,".");print a[2]" "$1}' file | sed 's/^./\U&/'
Emailclient name1@gmail.com
Socialsite name2@msn.com
Chris Seymour
  • 83,387
  • 30
  • 160
  • 202
4

Maybe your file contains CRLF terminator. Every lines followed by \r\n.

awk recognizes the $2 actually $2\r. The \r means goto the start of the line.

{print $2\r$1} will print $2 first, then return to the head, then print $1. So the field 2 is overlaid by the field 1.

jww
  • 97,681
  • 90
  • 411
  • 885
  • Welcome to Stack Overflow, SleepyProgrammer! I recommend you to add more details if you can. This post looks like a comment and might be removed... – Badacadabra Jun 27 '17 at 17:33
  • Thanks a lot for this tip, that was the case when there is only a single column, so I just want to append another column, but `$0` (or `$1`) returns a string ending with `\r` which causes this unexpected behavior of "overlaying" the initial column. – Oleg Afanasyev May 23 '23 at 21:26
3

Use a dot or a pipe as the field separator:

awk -v FS='[.|]' '{
    printf "%s%s %s.%s\n", toupper(substr($4,1,1)), substr($4,2), $1, $2
}' << END
name1@gmail.com|com.emailclient.account
name2@msn.com|com.socialsite.auth.account
END

gives:

Emailclient name1@gmail.com
Socialsite name2@msn.com
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
2

The awk is ok. I'm guessing the file is from a windows system and has a CR (^m ascii 0x0d) on the end of the line.

This will cause the cursor to go to the start of the line after $2.

Use dos2unix or vi with :se ff=unix to get rid of the CRs.

parkydr
  • 7,596
  • 3
  • 32
  • 42