I need help with this shell script.
- Must use a loop of some sort.
- Must use input data exactly as shown.
- Output redirection should be accomplished within the script, not on the command line.
Here's the input files I have: http://pastebin.com/m3f783597
Here's what the output needs to be: http://pastebin.com/m2c53b25a
Here's my failed attempt: http://pastebin.com/m2c60b41
And that failed attempt's output: http://pastebin.com/m3460e78c
-
This is homework, I assume?
Read up on the sort and paste commands:
man sort,man paste -
Here's the help. Try to follow these as much as possible before looking at my solution below. That will help you out more in the long run, and in the short runsince it's a certainty that your educator can see this as easily as you can.
If he finds you've plagiarized code, it will probably mean an instant fail.
Your "failed attempt" as you put it is here. It's actually not too bad for a first attempt.
echo -e "Name\t\t On-Call\t\t Phone" for daycount in 2 1 4 5 7 6 3 do for namecount in 3 2 6 1 7 4 5 do day=`head -n $daycount p2input2|tail -n 1|cut -f 2 -d " "` name=`head -n $namecount p2input1|tail -n 1|cut -f 1 -d " "` phone=`head -n $namecount p2input1|tail -n 1|cut -f 2 -d " "` echo -e "$name\c" echo -e "\t\t$day\c" echo -e "\t\t$phone" continue done doneAnd here's the hints:
- You have two loops, one inside the other, each occurring 7 times. That means 49 lines of output rather than 7. You want to process each day and look up up name and phone for that day (actually name for that day and phone for that name).
- It's not really suitable hardcoding linenumbers (although I admit it is sneaky)- what if the order of data changes? Better to search on values.
- Tabs make things messy, use spaces instead since then the output doesn't rely on terminal settings and you don't need to worry about misaligned tabs.
And, for completeness, here's the two input files and the expected output:
p2input1 p2input2 ======== ======== Dave 734.838.9801 Bob Tuesday Bob 313.123.4567 Carol Monday Carol 248.344.5576 Ted Sunday Mary 313.449.1390 Alice Wednesday Ted 248.496.2204 Dave Thursday Alice 616.556.4458 Mary Saturday Frank 634.296.3357 Frank Friday Expected output =============== Name On-Call Phone carol monday 248.344.5576 bob tuesday 313.123.4567 alice wednesday 616.556.4458 dave thursday 734.838.9801 frank friday 634.296.3357 mary saturday 313.449.1390 ted sunday 248.496.2204Having said all that, and assuming you've gone away for at least two hours to try and get your version running, here's mine:
1 #!/bin/bash 2 spc20=" " 3 echo "Name On-Call Phone" 4 echo 5 for day in monday tuesday wednesday thursday friday saturday sunday 6 do 7 name=`grep -i " ${day}$" p2input2 | awk '{print $1}'` 8 name=`echo ${name} | tr '[A-Z]' '[a-z]'` 9 bigname=`echo "${name}${spc20}" | cut -c1-15` 10 11 bigday=`echo "${day}${spc20}" | cut -c1-15` 12 13 phone=`grep -i "^${name} " p2input1 | awk '{print $2}'` 14 15 echo "${bigname} ${bigday} ${phone}" 16 doneAnd the following description should help:
- Line 1elects the right shell, not always necessary.
- Line 2 gives us enough spaces to make formatting easier.
- Lines 3-4 give us the title and blank line.
- Lines 5-6 cycles through the days, one at a time.
- Line 7 gives us a name for the day.
'grep -i " ${day}$"'searches for the given day (regardless of upper or lower case) at the end of a line inpinput2while the awk statement gives you field 1 (the name). - Line 8 simply makes the name all lowercase.
- Line 9 creates a string of the right size for output by adding 50 spaces then cutting off all at the end except for 15.
- Line 11 does the same for the day.
- Line 13 is very similar to line 7 except it searches
pinput1, looks for the name at the start of the line and returns the phone number as the second field. - Line 15 just outputs the individual items.
- Line 16 ends the loop.
So there you have it, enough hints to (hopefully) fix up your own code, and a sample as to how a professional would do it :-).
It would be wise to read up on the tools used,
grep,tr,cutandawk. -
Pax has given a good answer, but this code invokes fewer processes (11 vs a minimum of 56 = 7 * 8). It uses an auxilliary data file to give the days of the week and their sequence number.
cat <<! >p2input3 1 Monday 2 Tuesday 3 Wednesday 4 Thursday 5 Friday 6 Saturday 7 Sunday ! sort +1 p2input3 > p2.days sort +1 p2input2 > p2.call join -1 2 -2 2 p2.days p2.call | sort +2 > p2.duty sort +0 p2input1 > p2.body join -1 3 -2 1 p2.duty p2.body | sort +2n | tr '[A-Z]' '[a-z]' | awk 'BEGIN { printf("%-14s %-14s %s\n", "Name", "On-Call", "Phone"); printf "\n"; } { printf("%-14s %-14s %s\n", $1, $2, $4);}' rm -f p2input3 p2.days p2.call p2.duty p2.bodyThe
joincommand is powerful, but requires the data in the two files in sorted order on the joining keys. Thecatcommand gives a list of days and the day number. The first sort places that list in alphabetic order of day name. The second sort places the names of the people on duty in alphabetic order of day name too. The first join then combines those two files on day name, and then sorts based on user name, yielding the output:Wednesday 3 Alice Tuesday 2 Bob Monday 1 Carol Thursday 4 Dave Friday 5 Frank Saturday 6 Mary Sunday 7 TedThe last sort puts the names and phone numbers into alphabetic name order. The second join then combines the name + phone number list with the name + duty list, yielding a 4 column output. This is run through
trto make the data all lower case, and then formatted withawk, which demonstrates its power and simplicity nicely here (you could use Perl or Python instead, but frankly, that would be messier).Perl has a motto: TMTOWTDI "There's more than one way to do it".
That often applies to shell scripting too.
I suppose my code does not use a loop...oh dear. Replace the initial
catcommand with:for day in "1 Monday" "2 Tuesday" "3 Wednesday" "4 Thursday" \ "5 Friday" "6 Saturday" "7 Sunday" do echo $day done > p2input3This now meets the letter of the rules.
-
Try this one:
sort file1.txt > file1sort.txt sort file2.txt > file2sort.txt join file2sort.txt file1sort.txt | column -t > result.txt rm file1sort.txt file2sort.txt
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.