Wednesday, May 7, 2014

Unix Shell Example: Creating Office Directory

text file:
 01:bg:Bill Gates/Seattle/Washington  
 02:sj:Steve Jobs/San Francisco/California  
 03:mb:Michael Bloomberg/New York City/New York  

Our job is trying to re-format the text into following format:
 
 Gates, Bill                Seattle            Washington  
 Bloomberg, Michael         New York City        New York  
 Jobs, Steve                San Francisco      California  

Script:
 #! /bin/bash  
 umask 077 #setup the temporary file only could be accessed by this script  
 PERSON="./person.$$" #$$ represents the process number  
 CITY="./city.$$"  
 STATE="./state.$$"  
 USER="./user.$$"  

 # Using ":" as the separator, output 2nd and 3rd field to $USER  
 awk -F: '{ print $2 ":" $3 }' < ./text >$USER  

 cat $USER  
 #output  
 #bg:Bill Gates/Seattle/Washington  
 #sj:Steve Jobs/San Francisco/California  
 #mb:Michael Bloomberg/New York City/New York  

 #First sed command: we remove all words after '/'  
 #Second sed command: we reverse the position of last name and first name  
 #Then we use ":" as separator sort based on first field  
 sed -e 's=/.*==' -e 's=:\(.*\) \(.*\)=:\2, \1=' < $USER \  
  | sort -t: -k1 > $PERSON  

 cat $PERSON  
 #output:  
 #bg:Gates, Bill  
 #mb:Bloomberg, Michael  
 #sj:Jobs, Steve  

 #the only sed command is used to remove name and state from text  
 #then sort, output to file $CITY  
 sed -e 's=:.*/\(.*\)/.*=:\1=' <$USER \  
  | sort -t: -k1 > $CITY  

 cat $CITY  
 #output:  
 #bg:Seattle  
 #mb:New York City  
 #sj:San Francisco  

 #similar as above, remove the name and city from text  
 sed -e 's=:.*/.*/\(.*\)=:\1=' <$USER \  
  | sort -t: -k1 > $STATE  

 cat $STATE  
 #output:  
 #bg:Washington  
 #mb:New York  
 #sj:California  

 # First command in the pipe:  
 # using ":" as the separator we are trying to join the $PERSON $CITY  
 # with the first field, output:  
 #bg:Gates, Bill:Seattle  
 #mb:Bloomberg, Michael:New York City  
 #sj:Jobs, Steve:San Francisco  

 # Second Command in the pipe:  
 # using ":" as the separator we are trying to join the above result  
 # and $STATE based on first field by default, output:  
 #bg:Gates, Bill:Seattle:Washington  
 #mb:Bloomberg, Michael:New York City:New York  
 #sj:Jobs, Steve:San Francisco:California  

 # Third Command in the pipe:  
 # using ":" as the separator, we are trying to retrieve fields  
 # from 2nd to the end, based on above result, output:  
 #Gates, Bill:Seattle:Washington  
 #Bloomberg, Michael:New York City:New York  
 #Jobs, Steve:San Francisco:California  

 # Fourth Command in the pipe:  
 # using ":" as the separator, we are printing out the entire text  
 # with some format, "%-20s" means, output the string starting from  
 # left side at the space of 20 characters long width.  
 join -t ":" $PERSON $CITY \  
  | join -t ":" - $STATE \  
  | cut -d ":" -f 2- \  
  | awk -F: '{ printf "%-20s\t%+20s\t%+15s\n", $1, $2, $3 }'  

 #output:  
 #Gates, Bill                Seattle       Washington  
 #Bloomberg, Michael         New York City        New York  
 #Jobs, Steve             San Francisco       California  

 trap "exit 1"  
 trap "rm -f $PERSON $CITY $STATE $USER" EXIT  

No comments:

Post a Comment