1

i'm having a bit of a problem and i've been searching allll day. this is my first Unix class don't be to harsh.

so this may sound fairly simple, but i can't get it

I have two text files

file1

David 734.838.9801
Roberto‭ ‬313.123.4567
Sally‭ ‬248.344.5576
Mary‭ ‬313.449.1390
Ted‭ ‬248.496.2207
Alice‭ ‬616.556.4458
Frank‭ ‬634.296.1259

file2

Roberto Tuesday‭ ‬2
Sally Monday‭ ‬8
Ted Sunday‭ ‬16
Alice Wednesday‭ ‬23
David Thursday‭ ‬10
Mary Saturday‭ ‬14
Frank Friday‭ ‬15

I am trying to write a script using a looping structure that will combine both files and come out with the output below as a separate file

output:

Name       On-Call    Phone        Start Time

Sally      Monday     248.344.5576  8am

Roberto    Tuesday    313.123.4567  2am

Alice‭      Wednesday‭  616.556.4458‭  11pm

David‭      Thursday‭   734.838.9801‭  10am

Frank‭      Friday‭     634.296.1259‭   3pm

Mary‭       Saturday‭   313.449.1390‭   2pm

Ted‭ ‬       Sunday‭     248.496.2207‭   4pm

This is what i tried( i know its horrible)

echo " Name     On-Call          Phone      Start Time"
file="/home/xubuntu/date.txt"
file1="/home/xubuntu/name.txt"
while read name2 phone
do
while read name day time
do
echo "$name     $day   $phone           $time"
done<"$file"
done<"$file1"

any help would be appreciated

Chandranshu
  • 3,669
  • 3
  • 20
  • 37
  • there is an efficient way of doing this...use paste – Vinayak Pahalwan Nov 25 '13 at 06:27
  • @Chandranshu Advertising your own answer? Give the man some time to try out both answers. Also, there might come in better answers after a few hours :) – Bernhard Nov 25 '13 at 07:33
  • thanks for the help, for some reason i'm getting an error awk: 1: unexpected character '&' – bypass_override Nov 25 '13 at 07:36
  • @Chandranshu http://meta.stackexchange.com/questions/136951/lets-stop-displaying-a-users-accept-rate/136956#136956 – Bernhard Nov 25 '13 at 07:38
  • sorry i'm a super noob at this stuff – bypass_override Nov 25 '13 at 07:39
  • @bypass_override - `|&` is a gawk extension. You may not have that feature in your implementation of awk. You should simply use `|` without the `&`. The advantage of using `|&` is that the command is run as a co-process saving precious start-up time on each iteration. – Chandranshu Nov 25 '13 at 07:40

2 Answers2

2

First, sort the files using sort and then use this command:

paste file1 file2 | awk '{print $1,$4,$2,$5}'

This will bring you pretty close. After that you have to figure out how to format the time from the 24 hour format to the 12 hour format.

If you want to avoid using sort separately, you can bring in a little more complexity like this:

paste <(sort file1) <(sort file2) | awk '{print $1,$4,$2,$5}'

Finally, if you have not yet figured out how to print the time in 12 hour format, here is your full command:

paste <(sort file1) <(sort file2) | awk '{"date --date=\"" $5 ":00:00\" +%I%P" |& getline $5; print $1 " " $4 " " $2 " " $5 }'

You can use tabs (\t) in place of spaces as connectors to get a nicely formatted output.

Chandranshu
  • 3,669
  • 3
  • 20
  • 37
  • paste will just combine columns from both the files irrespective of any common columns. But here it needs to be joined based on common column.. – Mariappan Subramanian Nov 25 '13 at 06:56
  • hi, thanks for the reply, it did work, but is there any way i can produce the same outcome but with a looping structure? – bypass_override Nov 25 '13 at 06:58
  • @Mari - That's why the sort gets involved. It ensures that corresponding lines on each file have the same name. – Chandranshu Nov 25 '13 at 07:07
  • @bypass_override - Yes, you can always loop over both the result sets but that solution will take you O(n^2) time assuming you have n lines in each file. The presented solution takes O(n log n) time. – Chandranshu Nov 25 '13 at 07:08
  • yeah @Chandranshu Got it :) thanks for the clarification. I just posted alternative method with join command. please let me know incase it has any problems. I tested it though.. – Mariappan Subramanian Nov 25 '13 at 07:11
2

In this case join command will also work,

join -1 1 -2 1 <(sort file1) <(sort file2)

Description

-1 -> file1
1  -> first field of file1 (common field)
-2 -> file2
1 -> first field of file2 (common field)


**cat file1**

David 734.838.9801
Roberto 313.123.4567
Sally 248.344.5576
Mary 313.449.1390
Ted 248.496.2207
Alice 616.556.4458
Frank 634.296.1259

**cat file2**

Roberto Tuesday 2
Sally Monday 8
Ted Sunday 16
Alice Wednesday 23
David Thursday 10
Mary Saturday 14
Frank Friday 15

output

Alice 616.556.4458 Wednesday 23
David 734.838.9801 Thursday 10
Frank 634.296.1259 Friday 15
Mary 313.449.1390 Saturday 14
Roberto 313.123.4567 Tuesday 2
Sally 248.344.5576 Monday 8
Ted 248.496.2207 Sunday 16
Mariappan Subramanian
  • 9,527
  • 8
  • 32
  • 33
  • There is one little problem: join expects the input files to be sorted. Here is the relevant section from the man page: Important: FILE1 and FILE2 must be sorted on the join fields. E.g., use ` sort -k 1b,1 ' if `join' has no options, or use ` join -t '' ' if `sort' has no options. The other issue which may or may not be a problem for the OP is that you can't specify the order of columns in the output. – Chandranshu Nov 25 '13 at 07:16
  • As shown by your output, join has ignored the rows where it couldn't find a match through a forward iteration. – Chandranshu Nov 25 '13 at 07:17
  • yes right @Chandranshu . . So it needs files to be sorted.. let me edit it. thanks for your input.. – Mariappan Subramanian Nov 25 '13 at 07:20
  • You can simply use this command: `join -1 1 -2 1 <(sort file1) <(sort file2)`. I'd have preferred to use `join` myself unless there was a transformation of hours involved. – Chandranshu Nov 25 '13 at 07:21
  • yeah right exactly.. since it's joining based on common column, I preferred to use join command.. – Mariappan Subramanian Nov 25 '13 at 07:23
  • I just updated the answer.. thanks for your input @Chandranshu . . learnt this stuff and paste stuff – Mariappan Subramanian Nov 25 '13 at 07:25